TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
BackendLayoutView.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\View;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
21 
26 {
31 
36 
40  protected $selectedBackendLayout = [];
41 
45  public function __construct()
46  {
47  $this->initializeDataProviderCollection();
48  }
49 
55  protected function initializeDataProviderCollection()
56  {
59  BackendLayout\DataProviderCollection::class
60  );
61 
63  'default',
64  \TYPO3\CMS\Backend\View\BackendLayout\DefaultDataProvider::class
65  );
66 
67  if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider'])) {
68  $dataProviders = (array)$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider'];
69  foreach ($dataProviders as $identifier => $className) {
70  $dataProviderCollection->add($identifier, $className);
71  }
72  }
73 
75  }
76 
80  public function setDataProviderCollection(BackendLayout\DataProviderCollection $dataProviderCollection)
81  {
82  $this->dataProviderCollection = $dataProviderCollection;
83  }
84 
88  public function getDataProviderCollection()
89  {
91  }
92 
100  public function addBackendLayoutItems(array $parameters)
101  {
102  $pageId = $this->determinePageId($parameters['table'], $parameters['row']);
103  $pageTsConfig = (array)BackendUtility::getPagesTSconfig($pageId);
104  $identifiersToBeExcluded = $this->getIdentifiersToBeExcluded($pageTsConfig);
105 
106  $dataProviderContext = $this->createDataProviderContext()
107  ->setPageId($pageId)
108  ->setData($parameters['row'])
109  ->setTableName($parameters['table'])
110  ->setFieldName($parameters['field'])
111  ->setPageTsConfig($pageTsConfig);
112 
113  $backendLayoutCollections = $this->getDataProviderCollection()->getBackendLayoutCollections($dataProviderContext);
114  foreach ($backendLayoutCollections as $backendLayoutCollection) {
115  $combinedIdentifierPrefix = '';
116  if ($backendLayoutCollection->getIdentifier() !== 'default') {
117  $combinedIdentifierPrefix = $backendLayoutCollection->getIdentifier() . '__';
118  }
119 
120  foreach ($backendLayoutCollection->getAll() as $backendLayout) {
121  $combinedIdentifier = $combinedIdentifierPrefix . $backendLayout->getIdentifier();
122 
123  if (in_array($combinedIdentifier, $identifiersToBeExcluded, true)) {
124  continue;
125  }
126 
127  $parameters['items'][] = [
128  $this->getLanguageService()->sL($backendLayout->getTitle()),
129  $combinedIdentifier,
130  $backendLayout->getIconPath(),
131  ];
132  }
133  }
134  }
135 
143  protected function determinePageId($tableName, array $data)
144  {
145  if (strpos($data['uid'], 'NEW') === 0) {
146  // negative uid_pid values of content elements indicate that the element
147  // has been inserted after an existing element so there is no pid to get
148  // the backendLayout for and we have to get that first
149  if ($data['pid'] < 0) {
150  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
151  ->getQueryBuilderForTable($tableName);
152  $queryBuilder->getRestrictions()
153  ->removeAll();
154  $pageId = $queryBuilder
155  ->select('pid')
156  ->from($tableName)
157  ->where(
158  $queryBuilder->expr()->eq(
159  'uid',
160  $queryBuilder->createNamedParameter(abs($data['pid']), \PDO::PARAM_INT)
161  )
162  )
163  ->execute()
164  ->fetchColumn();
165  } else {
166  $pageId = $data['pid'];
167  }
168  } elseif ($tableName === 'pages') {
169  $pageId = $data['uid'];
170  } else {
171  $pageId = $data['pid'];
172  }
173 
174  return $pageId;
175  }
176 
183  public function getSelectedCombinedIdentifier($pageId)
184  {
185  if (!isset($this->selectedCombinedIdentifier[$pageId])) {
186  $page = $this->getPage($pageId);
187  $this->selectedCombinedIdentifier[$pageId] = (string)$page['backend_layout'];
188 
189  if ($this->selectedCombinedIdentifier[$pageId] === '-1') {
190  // If it is set to "none" - don't use any
191  $this->selectedCombinedIdentifier[$pageId] = false;
192  } elseif ($this->selectedCombinedIdentifier[$pageId] === '' || $this->selectedCombinedIdentifier[$pageId] === '0') {
193  // If it not set check the root-line for a layout on next level and use this
194  // (root-line starts with current page and has page "0" at the end)
195  $rootLine = $this->getRootLine($pageId);
196  // Remove first and last element (current and root page)
197  array_shift($rootLine);
198  array_pop($rootLine);
199  foreach ($rootLine as $rootLinePage) {
200  $this->selectedCombinedIdentifier[$pageId] = (string)$rootLinePage['backend_layout_next_level'];
201  if ($this->selectedCombinedIdentifier[$pageId] === '-1') {
202  // If layout for "next level" is set to "none" - don't use any and stop searching
203  $this->selectedCombinedIdentifier[$pageId] = false;
204  break;
205  } elseif ($this->selectedCombinedIdentifier[$pageId] !== '' && $this->selectedCombinedIdentifier[$pageId] !== '0') {
206  // Stop searching if a layout for "next level" is set
207  break;
208  }
209  }
210  }
211  }
212  // If it is set to a positive value use this
213  return $this->selectedCombinedIdentifier[$pageId];
214  }
215 
222  protected function getIdentifiersToBeExcluded(array $pageTSconfig)
223  {
224  $identifiersToBeExcluded = [];
225 
226  if (ArrayUtility::isValidPath($pageTSconfig, 'options./backendLayout./exclude')) {
227  $identifiersToBeExcluded = GeneralUtility::trimExplode(
228  ',',
229  ArrayUtility::getValueByPath($pageTSconfig, 'options./backendLayout./exclude'),
230  true
231  );
232  }
233 
234  return $identifiersToBeExcluded;
235  }
236 
245  public function colPosListItemProcFunc(array $parameters)
246  {
247  $pageId = $this->determinePageId($parameters['table'], $parameters['row']);
248 
249  if ($pageId !== false) {
250  $parameters['items'] = $this->addColPosListLayoutItems($pageId, $parameters['items']);
251  }
252  }
253 
261  protected function addColPosListLayoutItems($pageId, $items)
262  {
263  $layout = $this->getSelectedBackendLayout($pageId);
264  if ($layout && $layout['__items']) {
265  $items = $layout['__items'];
266  }
267  return $items;
268  }
269 
276  public function getColPosListItemsParsed($id)
277  {
278  $tsConfig = BackendUtility::getModTSconfig($id, 'TCEFORM.tt_content.colPos');
279  $tcaConfig = $GLOBALS['TCA']['tt_content']['columns']['colPos']['config'];
280  $tcaItems = $tcaConfig['items'];
281  $tcaItems = $this->addItems($tcaItems, $tsConfig['properties']['addItems.']);
282  if (isset($tcaConfig['itemsProcFunc']) && $tcaConfig['itemsProcFunc']) {
283  $tcaItems = $this->addColPosListLayoutItems($id, $tcaItems);
284  }
285  foreach (GeneralUtility::trimExplode(',', $tsConfig['properties']['removeItems'], true) as $removeId) {
286  foreach ($tcaItems as $key => $item) {
287  if ($item[1] == $removeId) {
288  unset($tcaItems[$key]);
289  }
290  }
291  }
292  return $tcaItems;
293  }
294 
306  protected function addItems($items, $iArray)
307  {
308  $languageService = static::getLanguageService();
309  if (is_array($iArray)) {
310  foreach ($iArray as $value => $label) {
311  // if the label is an array (that means it is a subelement
312  // like "34.icon = mylabel.png", skip it (see its usage below)
313  if (is_array($label)) {
314  continue;
315  }
316  // check if the value "34 = mylabel" also has a "34.icon = myimage.png"
317  if (isset($iArray[$value . '.']) && $iArray[$value . '.']['icon']) {
318  $icon = $iArray[$value . '.']['icon'];
319  } else {
320  $icon = '';
321  }
322  $items[] = [$languageService->sL($label), $value, $icon];
323  }
324  }
325  return $items;
326  }
327 
334  public function getSelectedBackendLayout($pageId)
335  {
336  if (isset($this->selectedBackendLayout[$pageId])) {
337  return $this->selectedBackendLayout[$pageId];
338  }
339  $backendLayoutData = null;
340 
342  // If no backend layout is selected, use default
343  if (empty($selectedCombinedIdentifier)) {
344  $selectedCombinedIdentifier = 'default';
345  }
346 
347  $backendLayout = $this->getDataProviderCollection()->getBackendLayout($selectedCombinedIdentifier, $pageId);
348  // If backend layout is not found available anymore, use default
349  if (is_null($backendLayout)) {
350  $selectedCombinedIdentifier = 'default';
351  $backendLayout = $this->getDataProviderCollection()->getBackendLayout($selectedCombinedIdentifier, $pageId);
352  }
353 
354  if (!empty($backendLayout)) {
356  $parser = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::class);
358  $conditionMatcher = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher::class);
359  $parser->parse($parser->checkIncludeLines($backendLayout->getConfiguration()), $conditionMatcher);
360 
361  $backendLayoutData = [];
362  $backendLayoutData['config'] = $backendLayout->getConfiguration();
363  $backendLayoutData['__config'] = $parser->setup;
364  $backendLayoutData['__items'] = [];
365  $backendLayoutData['__colPosList'] = [];
366 
367  // create items and colPosList
368  if (!empty($backendLayoutData['__config']['backend_layout.']['rows.'])) {
369  foreach ($backendLayoutData['__config']['backend_layout.']['rows.'] as $row) {
370  if (!empty($row['columns.'])) {
371  foreach ($row['columns.'] as $column) {
372  if (!isset($column['colPos'])) {
373  continue;
374  }
375  $backendLayoutData['__items'][] = [
376  $this->getColumnName($column),
377  $column['colPos'],
378  null
379  ];
380  $backendLayoutData['__colPosList'][] = $column['colPos'];
381  }
382  }
383  }
384  }
385 
386  $this->selectedBackendLayout[$pageId] = $backendLayoutData;
387  }
388 
389  return $backendLayoutData;
390  }
391 
398  public static function getDefaultColumnLayout()
399  {
400  return '
401  backend_layout {
402  colCount = 4
403  rowCount = 1
404  rows {
405  1 {
406  columns {
407  1 {
408  name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.0
409  colPos = 1
410  }
411  2 {
412  name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.1
413  colPos = 0
414  }
415  3 {
416  name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.2
417  colPos = 2
418  }
419  4 {
420  name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.3
421  colPos = 3
422  }
423  }
424  }
425  }
426  }
427  ';
428  }
429 
436  protected function getPage($pageId)
437  {
438  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
439  ->getQueryBuilderForTable('pages');
440  $queryBuilder->getRestrictions()
441  ->removeAll();
442  $page = $queryBuilder
443  ->select('uid', 'pid', 'backend_layout')
444  ->from('pages')
445  ->where(
446  $queryBuilder->expr()->eq(
447  'uid',
448  $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
449  )
450  )
451  ->execute()
452  ->fetch();
453  BackendUtility::workspaceOL('pages', $page);
454 
455  return $page;
456  }
457 
464  protected function getRootLine($pageId)
465  {
466  return BackendUtility::BEgetRootLine($pageId, '', true);
467  }
468 
472  protected function createDataProviderContext()
473  {
474  return GeneralUtility::makeInstance(BackendLayout\DataProviderContext::class);
475  }
476 
480  protected function getLanguageService()
481  {
482  return $GLOBALS['LANG'];
483  }
484 
491  protected function getColumnName($column)
492  {
493  $columnName = $column['name'];
494 
495  if (GeneralUtility::isFirstPartOfStr($columnName, 'LLL:')) {
496  $columnName = $this->getLanguageService()->sL($columnName);
497  }
498 
499  return $columnName;
500  }
501 }
static isFirstPartOfStr($str, $partStr)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static getValueByPath(array $array, $path, $delimiter= '/')
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
static BEgetRootLine($uid, $clause= '', $workspaceOL=false)
static getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
setDataProviderCollection(BackendLayout\DataProviderCollection $dataProviderCollection)
static makeInstance($className,...$constructorArguments)
static isValidPath(array $array, $path, $delimiter= '/')