‪TYPO3CMS  11.5
AbstractContentPagePositionMap.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 TYPO3\CMS\Backend\Utility\BackendUtility;
31 
33 {
37  public int ‪$cur_sys_language = 0;
38 
40 
42  {
43  $this->backendLayoutView = ‪$backendLayoutView;
44  }
45 
55  abstract protected function ‪insertPositionIcon(?array $row, int $colPos, int $pid): string;
56 
63  abstract protected function ‪getRecordHeader(array $row): string;
64 
71  public function ‪printContentElementColumns(int $pid): string
72  {
73  $lines = [];
74  $columnsConfiguration = $this->‪getColumnsConfiguration($pid);
75  foreach ($columnsConfiguration as $columnConfiguration) {
76  if ($columnConfiguration['isRestricted']) {
77  // Do not fetch records of restricted columns
78  continue;
79  }
80  $colPos = $columnConfiguration['colPos'];
81  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
82  $queryBuilder
83  ->getRestrictions()
84  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace))
85  ->removeByType(HiddenRestriction::class)
86  ->removeByType(StartTimeRestriction::class)
87  ->removeByType(EndTimeRestriction::class);
88  $queryBuilder
89  ->select('*')
90  ->from('tt_content')
91  ->where(
92  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, ‪Connection::PARAM_INT)),
93  $queryBuilder->expr()->eq('colPos', $queryBuilder->createNamedParameter($colPos, ‪Connection::PARAM_INT))
94  )
95  ->orderBy('sorting');
96 
97  if ((string)$this->cur_sys_language !== '') {
98  $queryBuilder->andWhere(
99  $queryBuilder->expr()->eq(
100  'sys_language_uid',
101  $queryBuilder->createNamedParameter($this->cur_sys_language, ‪Connection::PARAM_INT)
102  )
103  );
104  }
105 
106  $res = $queryBuilder->executeQuery();
107  $lines[$colPos] = [
108  $this->‪insertPositionIcon(null, $colPos, $pid),
109  ];
110 
111  while ($row = $res->fetchAssociative()) {
112  BackendUtility::workspaceOL('tt_content', $row);
113  if (is_array($row)) {
114  $lines[$colPos][] = $this->‪getRecordHeader($row);
115  $lines[$colPos][] = $this->‪insertPositionIcon($row, $colPos, $pid);
116  }
117  }
118  }
119  return $this->‪printRecordMap($lines, $columnsConfiguration, $pid);
120  }
121 
130  protected function ‪printRecordMap(array $lines, array $tcaColumnsConfiguration, int $pid): string
131  {
132  $lang = $this->‪getLanguageService();
133  $lang->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
134  $hideRestrictedColumns = (bool)(BackendUtility::getPagesTSconfig($pid)['mod.']['web_layout.']['hideRestrictedCols'] ?? false);
135  $backendLayout = $this->backendLayoutView->getSelectedBackendLayout($pid);
136 
137  if (isset($backendLayout['__config']['backend_layout.'])) {
138  // Build position map based on the fetched backend layout
139  $colCount = (int)($backendLayout['__config']['backend_layout.']['colCount'] ?? 0);
140  $rowCount = (int)($backendLayout['__config']['backend_layout.']['rowCount'] ?? 0);
141 
142  // Cycle through rows
143  $tableRows = [];
144  for ($row = 1; $row <= $rowCount; $row++) {
145  $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'] ?? null;
146  if (!$rowConfig) {
147  // Skip empty rows
148  continue;
149  }
150 
151  // Cycle through cells
152  $tableCells = [];
153  for ($col = 1; $col <= $colCount; $col++) {
154  $columnConfig = $rowConfig['columns.'][$col . '.'] ?? null;
155  if (!$columnConfig) {
156  // Skip empty columns
157  continue;
158  }
159 
160  // Set table cell attributes
161  $tableCellAttributes = [
162  'class' => 'col-nowrap col-min',
163  ];
164  if (isset($columnConfig['colspan'])) {
165  $tableCellAttributes['colspan'] = $columnConfig['colspan'];
166  }
167  if (isset($columnConfig['rowspan'])) {
168  $tableCellAttributes['rowspan'] = $columnConfig['rowspan'];
169  }
170 
171  $columnKey = null;
172  $columnTitle = '';
173  $isRestricted = false;
174  $isUnassigned = true;
175  if (isset($columnConfig['colPos'])) {
176  // If colPos is defined, initialize column information (e.g. title and restricted state)
177  $columnKey = (int)$columnConfig['colPos'];
178  foreach ($tcaColumnsConfiguration as $tcaColumnConfiguration) {
179  if ($tcaColumnConfiguration['colPos'] === $columnKey) {
180  $columnTitle = '<strong>' . htmlspecialchars($lang->sL($tcaColumnConfiguration['title'])) . '</strong>';
181  $isRestricted = $tcaColumnConfiguration['isRestricted'];
182  $isUnassigned = false;
183  }
184  }
185  }
186 
187  // Generate the cell content, based on the columns' state (e.g. restricted or unassigned)
188  $cellContent = '';
189  if ($isRestricted) {
190  if ($hideRestrictedColumns) {
191  // Hide in case this column is not accessible and hideRestrictedColumns is set
192  $tableCellAttributes['class'] = 'hidden';
193  } else {
194  $cellContent = '
195  <p>
196  ' . $columnTitle . ' <em>(' . htmlspecialchars($lang->getLL('noAccess')) . ')</em>
197  </p>';
198  $tableCellAttributes['class'] .= ' bg-danger bg-opacity-25';
199  }
200  } elseif ($isUnassigned) {
201  if ($hideRestrictedColumns) {
202  // Hide in case this column is not assigned and hideRestrictedColumns is set
203  $tableCellAttributes['class'] = 'hidden';
204  } else {
205  $cellContent = '
206  <em>
207  ' . htmlspecialchars($lang->sL($columnConfig['name']) ?: '') . '
208  ' . ' (' . htmlspecialchars($lang->getLL('notAssigned')) . ')' . '
209  </em>';
210  $tableCellAttributes['class'] .= ' bg-warning bg-opacity-25';
211  }
212  } else {
213  // If not restricted and not unassigned, wrap column title and render list (if available)
214  $cellContent = '<p>' . $columnTitle . '</p>';
215  if (!empty($lines[$columnKey])) {
216  $cellContent .= '
217  <ul class="list-unstyled">
218  ' . implode(LF, array_map(static fn(string $line): string => '<li>' . $line . '</li>', $lines[$columnKey])) . '
219  </ul>';
220  }
221  }
222 
223  // Add the table cell
224  $tableCells[] = '<td ' . GeneralUtility::implodeAttributes($tableCellAttributes) . '>' . $cellContent . '</td>';
225  }
226 
227  // Add the table row
228  $tableRows[] = '<tr>' . implode(LF, $tableCells) . '</tr>';
229  }
230 
231  // Create the table content
232  $tableContent = '<tbody>' . implode(LF, $tableRows) . '</tbody>';
233  } else {
234  // Build position map based on TCA colPos configuration
235  $tableCells = [];
236  foreach ($tcaColumnsConfiguration as $tcaColumnConfiguration) {
237  if ($hideRestrictedColumns && $tcaColumnConfiguration['isRestricted']) {
238  // Skip in case this column is not accessible and restricted columns should be hidden
239  continue;
240  }
241 
242  // Generate the cell content, based on the columns' state (e.g. restricted or unassigned)
243  $tableCellClasses = 'col-nowrap col-min';
244  $columnTitle = '<strong>' . htmlspecialchars($tcaColumnConfiguration['title']) . '</strong>';
245  if ($tcaColumnConfiguration['isRestricted']) {
246  // If this colPos is restricted, add an information to the column title and color the cell
247  $tableCellClasses .= ' bg-danger bg-opacity-25';
248  $cellContent = '
249  <p>
250  ' . $columnTitle . ' <em>(' . htmlspecialchars($lang->getLL('noAccess')) . ')</em>
251  </p>';
252  } else {
253  // If not restricted, wrap column title and render list (if available)
254  $cellContent = '<p>' . $columnTitle . '</p>';
255  if (!empty($lines[$tcaColumnConfiguration['colPos']])) {
256  $cellContent .= '
257  <ul class="list-unstyled">
258  ' . implode(LF, array_map(static fn(string $line): string => '<li>' . $line . '</li>', $lines[$tcaColumnConfiguration['colPos']])) . '
259  </ul>';
260  }
261  }
262 
263  // Add the table cell
264  $tableCells[] = '<td class="' . $tableCellClasses . '">' . $cellContent . '</td>';
265  }
266 
267  // Create the table content
268  $tableContent = '<tbody><tr>' . implode(LF, $tableCells) . '</tr></tbody>';
269  }
270 
271  // Return the record map (table)
272  return '
273  <div class="table-fit">
274  <table class="table table-sm table-bordered table-vertical-top">
275  ' . $tableContent . '
276  </table>
277  </div>';
278  }
279 
284  protected function ‪getColumnsConfiguration(int $id): array
285  {
286  $columnsConfiguration = $this->backendLayoutView->getColPosListItemsParsed($id);
287  if ($columnsConfiguration === []) {
288  return [];
289  }
290 
291  // Prepare the columns configuration (using named keys, etc.)
292  foreach ($columnsConfiguration as &$item) {
293  $item = [
294  'title' => $item[0],
295  'colPos' => (int)$item[1],
296  'isRestricted' => false,
297  ];
298  }
299  unset($item);
300 
301  $sharedColPosList = trim(BackendUtility::getPagesTSconfig($id)['mod.']['SHARED.']['colPos_list'] ?? '');
302  if ($sharedColPosList !== '') {
303  $activeColPosArray = array_unique(‪GeneralUtility::intExplode(',', $sharedColPosList));
304  if (!empty($columnsConfiguration) && !empty($activeColPosArray)) {
305  foreach ($columnsConfiguration as &$item) {
306  if (!in_array((int)$item['colPos'], $activeColPosArray, true)) {
307  $item['isRestricted'] = true;
308  }
309  }
310  unset($item);
311  }
312  }
313 
314  return $columnsConfiguration;
315  }
316 
318  {
319  return ‪$GLOBALS['BE_USER'];
320  }
321 
323  {
324  return ‪$GLOBALS['LANG'];
325  }
326 }
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\getColumnsConfiguration
‪getColumnsConfiguration(int $id)
Definition: AbstractContentPagePositionMap.php:284
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\getRecordHeader
‪string getRecordHeader(array $row)
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:49
‪TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction
Definition: EndTimeRestriction.php:27
‪TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction
Definition: StartTimeRestriction.php:27
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\insertPositionIcon
‪string insertPositionIcon(?array $row, int $colPos, int $pid)
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\$backendLayoutView
‪BackendLayoutView $backendLayoutView
Definition: AbstractContentPagePositionMap.php:39
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\getLanguageService
‪getLanguageService()
Definition: AbstractContentPagePositionMap.php:322
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\__construct
‪__construct(BackendLayoutView $backendLayoutView)
Definition: AbstractContentPagePositionMap.php:41
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\printContentElementColumns
‪string printContentElementColumns(int $pid)
Definition: AbstractContentPagePositionMap.php:71
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Tree\View
Definition: AbstractContentPagePositionMap.php:18
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:38
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap
Definition: AbstractContentPagePositionMap.php:33
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:37
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:927
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\printRecordMap
‪string printRecordMap(array $lines, array $tcaColumnsConfiguration, int $pid)
Definition: AbstractContentPagePositionMap.php:130
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\getBackendUser
‪getBackendUser()
Definition: AbstractContentPagePositionMap.php:317
‪TYPO3\CMS\Backend\Tree\View\AbstractContentPagePositionMap\$cur_sys_language
‪int $cur_sys_language
Definition: AbstractContentPagePositionMap.php:37
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:40