‪TYPO3CMS  ‪main
ColumnSelectorController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseFactoryInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
29 
35 #[AsController]
37 {
38  private const ‪PSEUDO_FIELDS = ['_REF_', '_PATH_'];
39  private const ‪EXCLUDE_FILE_FIELDS = [
40  'pid', // Not relevant as all records are on pid=0
41  'identifier', // Handled manually in listing
42  'name', // Handled manually in listing
43  'metadata', // The reference to the meta data is not relevant
44  'file', // The reference to the file is not relevant
45  'sys_language_uid', // Not relevant in listing since only default is displayed
46  'l10n_parent', // Not relevant in listing
47  't3ver_state', // Not relevant in listing
48  't3ver_wsid', // Not relevant in listing
49  't3ver_oid', // Not relevant in listing
50  ];
51 
52  public function ‪__construct(
53  protected readonly ResponseFactoryInterface $responseFactory,
54  protected readonly ‪BackendViewFactory $backendViewFactory,
55  ) {}
56 
60  public function ‪updateVisibleColumnsAction(ServerRequestInterface $request): ResponseInterface
61  {
62  $parsedBody = $request->getParsedBody();
63  $table = (string)($parsedBody['table'] ?? '');
64  $selectedColumns = $parsedBody['selectedColumns'] ?? [];
65 
66  if ($table === '' || !is_array($selectedColumns)) {
67  return $this->‪jsonResponse([
68  'success' => false,
69  'message' => htmlspecialchars(
70  $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:updateColumnView.nothingUpdated')
71  ),
72  ]);
73  }
74 
75  $backendUser = $this->‪getBackendUserAuthentication();
76  $displayFields = $backendUser->getModuleData('list/displayFields');
77  $displayFields[$table] = $selectedColumns;
78  $backendUser->pushModuleData('list/displayFields', $displayFields);
79 
80  return $this->‪jsonResponse(['success' => true]);
81  }
82 
86  public function ‪showColumnsSelectorAction(ServerRequestInterface $request): ResponseInterface
87  {
88  $queryParams = $request->getQueryParams();
89  $table = (string)($queryParams['table'] ?? '');
90 
91  if ($table === '') {
92  throw new \RuntimeException('No table was given for selecting columns', 1625169125);
93  }
94  $view = $this->backendViewFactory->create($request);
95  $view->assignMultiple([
96  'table' => $table,
97  'columns' => $this->‪getColumns($table, (int)($queryParams['id'] ?? 0)),
98  ]);
99 
100  return $this->‪htmlResponse($view);
101  }
102 
106  protected function ‪getColumns(string $table, int $pageId): array
107  {
108  $tsConfig = BackendUtility::getPagesTSconfig($pageId);
109 
110  // Current fields selection
111  $displayFields = $this->‪getBackendUserAuthentication()->getModuleData('list/displayFields')[$table] ?? [];
112 
113  if ($table === '_FILE') {
114  // Special handling for _FILE (merging sys_file and sys_file_metadata together)
115  ‪$fields = $this->‪getFileFields();
116  } else {
117  // Request fields from table and add pseudo fields
118  ‪$fields = array_merge(BackendUtility::getAllowedFieldsForTable($table), self::PSEUDO_FIELDS);
119  }
120 
121  $columns = $specialColumns = $disabledColumns = [];
122  foreach (‪$fields as $fieldName) {
123  $concreteTableName = $table;
124 
125  // In case we deal with _FILE, the field name is prefixed with the
126  // concrete table name, which is either sys_file or sys_file_metadata.
127  if ($table === '_FILE') {
128  [$concreteTableName, $fieldName] = explode('|', $fieldName);
129  }
130 
131  // Hide field if disabled
132  if ($tsConfig['TCEFORM.'][$concreteTableName . '.'][$fieldName . '.']['disabled'] ?? false) {
133  continue;
134  }
135 
136  // Determine if the column should be disabled (Meaning it is always selected and can not be turned off)
137  $isDisabled = $fieldName === (‪$GLOBALS['TCA'][$concreteTableName]['ctrl']['label'] ?? false);
138 
139  // Determine field label
140  $label = BackendUtility::getItemLabel($concreteTableName, $fieldName);
141  $label = $this->‪getLanguageService()->translateLabel(
142  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$fieldName . '.']['label.'] ?? [],
143  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$fieldName . '.']['label']
144  ?? $label
145  ?? 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $fieldName
146  );
147 
148  // Add configuration for this column
149  $columnConfiguration = [
150  'name' => $fieldName,
151  'selected' => $isDisabled || in_array($fieldName, $displayFields, true),
152  'disabled' => $isDisabled,
153  'pseudo' => in_array($fieldName, self::PSEUDO_FIELDS, true),
154  'label' => $label,
155  ];
156 
157  // Add column configuration to the correct group
158  if ($columnConfiguration['disabled']) {
159  $disabledColumns[] = $columnConfiguration;
160  } elseif (!$columnConfiguration['label']) {
161  $specialColumns[] = $columnConfiguration;
162  } else {
163  $columns[] = $columnConfiguration;
164  }
165  }
166 
167  // Sort standard columns by their resolved label
168  usort($columns, static fn($a, $b) => $a['label'] <=> $b['label']);
169 
170  // Disabled columns go first, followed by standard columns
171  // and special columns, which do not have a label.
172  return array_merge($disabledColumns, $columns, $specialColumns);
173  }
174 
179  protected function ‪getFileFields(): array
180  {
181  // Get all sys_file fields expect excluded ones
182  $fileFields = array_filter(
183  BackendUtility::getAllowedFieldsForTable('sys_file'),
184  static fn(string $field): bool => !in_array($field, self::EXCLUDE_FILE_FIELDS, true)
185  );
186 
187  // Always add crdate and tstamp fields for files
188  $fileFields = array_unique(array_merge($fileFields, ['crdate', 'tstamp']));
189 
190  // Update the exclude fields with the fields, already added through sys_file, since those take precedence
191  $excludeFields = array_merge($fileFields, self::EXCLUDE_FILE_FIELDS);
192 
193  // Get all sys_file_metadata fields expect excluded ones
194  $fileMetaDataFields = array_filter(
195  BackendUtility::getAllowedFieldsForTable('sys_file_metadata'),
196  static fn(string $field): bool => !in_array($field, $excludeFields, true)
197  );
198 
199  // Merge sys_file and sys_file_metadata fields together, while adding the table name as prefix
200  return array_merge(
201  array_map(static fn(string $value): string => 'sys_file|' . $value, $fileFields),
202  array_map(static fn(string $value): string => 'sys_file_metadata|' . $value, $fileMetaDataFields),
203  );
204  }
205 
206  protected function ‪htmlResponse(‪ViewInterface $view): ResponseInterface
207  {
208  $response = $this->responseFactory
209  ->createResponse()
210  ->withHeader('Content-Type', 'text/html; charset=utf-8');
211  $response->getBody()->write($view->‪render('ColumnSelector'));
212  return $response;
213  }
214 
215  protected function ‪jsonResponse(array $data): ResponseInterface
216  {
217  $response = $this->responseFactory
218  ->createResponse()
219  ->withAddedHeader('Content-Type', 'application/json; charset=utf-8');
220 
221  $response->getBody()->write(json_encode($data));
222  return $response;
223  }
224 
226  {
227  return ‪$GLOBALS['BE_USER'];
228  }
229 
231  {
232  return ‪$GLOBALS['LANG'];
233  }
234 }
‪TYPO3\CMS\Core\View\ViewInterface\render
‪render(string $templateFileName='')
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\PSEUDO_FIELDS
‪const PSEUDO_FIELDS
Definition: ColumnSelectorController.php:38
‪TYPO3\CMS\Core\View\ViewInterface
Definition: ViewInterface.php:24
‪TYPO3\CMS\Backend\View\BackendViewFactory
Definition: BackendViewFactory.php:35
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\getFileFields
‪getFileFields()
Definition: ColumnSelectorController.php:179
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\getLanguageService
‪getLanguageService()
Definition: ColumnSelectorController.php:230
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\getColumns
‪getColumns(string $table, int $pageId)
Definition: ColumnSelectorController.php:106
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController
Definition: ColumnSelectorController.php:37
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\jsonResponse
‪jsonResponse(array $data)
Definition: ColumnSelectorController.php:215
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\EXCLUDE_FILE_FIELDS
‪const EXCLUDE_FILE_FIELDS
Definition: ColumnSelectorController.php:39
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\getBackendUserAuthentication
‪getBackendUserAuthentication()
Definition: ColumnSelectorController.php:225
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\updateVisibleColumnsAction
‪updateVisibleColumnsAction(ServerRequestInterface $request)
Definition: ColumnSelectorController.php:60
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\htmlResponse
‪htmlResponse(ViewInterface $view)
Definition: ColumnSelectorController.php:206
‪TYPO3\CMS\Backend\Controller
Definition: AboutController.php:18
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\showColumnsSelectorAction
‪showColumnsSelectorAction(ServerRequestInterface $request)
Definition: ColumnSelectorController.php:86
‪TYPO3\CMS\Backend\Controller\ColumnSelectorController\__construct
‪__construct(protected readonly ResponseFactoryInterface $responseFactory, protected readonly BackendViewFactory $backendViewFactory,)
Definition: ColumnSelectorController.php:52