PageLayoutController.php 52.4 KB
Newer Older
1
2
3
<?php
namespace TYPO3\CMS\Backend\Controller;

4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
8
9
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
10
 *
11
12
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
15
 * The TYPO3 project - inspiring people to share!
 */
16

Nicole Cordes's avatar
Nicole Cordes committed
17
18
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\Utility\IconUtility;
19
use TYPO3\CMS\Core\Type\Bitmask\Permission;
Nicole Cordes's avatar
Nicole Cordes committed
20
21
22
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Core\Utility\HttpUtility;
Nicole Cordes's avatar
Nicole Cordes committed
24
use TYPO3\CMS\Core\Utility\MathUtility;
25
use TYPO3\CMS\Fluid\View\StandaloneView;
26
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
27
28
29
30
31
32
33
34
35
36
37
use TYPO3\CMS\Recordlist\RecordList;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Frontend\Page\PageRepository;
use TYPO3\CMS\Backend\Module\ModuleLoader;
use TYPO3\CMS\Backend\Template\DocumentTemplate;
use TYPO3\CMS\Backend\View\BackendLayoutView;
use TYPO3\CMS\Backend\Form\DataPreprocessor;
use TYPO3\CMS\Backend\Form\FormEngine;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Backend\View\PageLayoutView;
use TYPO3\CMS\Backend\Tree\View\ContentLayoutPagePositionMap;
Nicole Cordes's avatar
Nicole Cordes committed
38

39
40
41
42
43
44
45
/**
 * Script Class for Web > Layout module
 *
 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
 */
class PageLayoutController {

46
47
48
49
50
	/**
	 * Page Id for which to make the listing
	 *
	 * @var int
	 */
51
52
	public $id;

53
54
55
56
57
	/**
	 * Pointer - for browsing list of records.
	 *
	 * @var int
	 */
58
59
	public $pointer;

60
61
62
63
64
	/**
	 * Thumbnails or not
	 *
	 * @var string
	 */
65
66
	public $imagemode;

67
68
69
70
71
	/**
	 * Search-fields
	 *
	 * @var string
	 */
72
73
	public $search_field;

74
75
76
77
78
	/**
	 * Search-levels
	 *
	 * @var int
	 */
79
80
	public $search_levels;

81
82
83
84
85
	/**
	 * Show-limit
	 *
	 * @var int
	 */
86
87
	public $showLimit;

88
89
90
91
92
	/**
	 * Return URL
	 *
	 * @var string
	 */
93
94
	public $returnUrl;

95
96
97
98
99
	/**
	 * Clear-cache flag - if set, clears page cache for current id.
	 *
	 * @var bool
	 */
100
101
	public $clear_cache;

102
103
104
105
106
	/**
	 * PopView id - for opening a window with the page
	 *
	 * @var bool
	 */
107
108
	public $popView;

109
110
111
112
113
114
	/**
	 * QuickEdit: Variable, that tells quick edit what to show/edit etc.
	 * Format is [tablename]:[uid] with some exceptional values for both parameters (with special meanings).
	 *
	 * @var string
	 */
115
116
	public $edit_record;

117
118
119
120
121
122
123
124
	/**
	 * QuickEdit: If set, this variable tells quick edit that the last edited record had
	 * this value as UID and we should look up the new, real uid value in sys_log.
	 *
	 * @var string
	 */
	public $new_unique_uid;

125
126
127
128
129
	/**
	 * Page select perms clause
	 *
	 * @var string
	 */
130
131
	public $perms_clause;

132
133
134
135
136
	/**
	 * Module TSconfig
	 *
	 * @var array
	 */
137
138
	public $modTSconfig;

139
140
141
142
143
144
145
	/**
	 * Module shared TSconfig
	 *
	 * @var array
	 */
	public $modSharedTSconfig;

146
147
148
149
150
	/**
	 * Current ids page record
	 *
	 * @var array
	 */
151
152
153
154
155
	public $pageinfo;

	/**
	 * Document template object
	 *
156
	 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
157
158
159
	 */
	public $doc;

160
161
162
163
164
	/**
	 * Back path of the module
	 *
	 * @var string
	 */
165
166
	public $backPath;

167
168
169
170
171
	/**
	 * "Pseudo" Description -table name
	 *
	 * @var string
	 */
172
173
	public $descrTable;

174
175
176
177
178
	/**
	 * List of column-integers to edit. Is set from TSconfig, default is "1,0,2,3"
	 *
	 * @var string
	 */
179
180
	public $colPosList;

181
182
183
184
185
	/**
	 * Flag: If content can be edited or not.
	 *
	 * @var bool
	 */
186
187
	public $EDIT_CONTENT;

188
189
190
191
192
	/**
	 * Users permissions integer for this page.
	 *
	 * @var int
	 */
193
194
	public $CALC_PERMS;

195
196
197
198
199
	/**
	 * Currently selected language for editing content elements
	 *
	 * @var int
	 */
200
201
	public $current_sys_language;

202
203
204
205
206
	/**
	 * Module configuration
	 *
	 * @var array
	 */
207
208
	public $MCONF = array();

209
210
211
212
213
	/**
	 * Menu configuration
	 *
	 * @var array
	 */
214
215
	public $MOD_MENU = array();

216
217
218
219
220
	/**
	 * Module settings (session variable)
	 *
	 * @var array
	 */
221
222
	public $MOD_SETTINGS = array();

223
224
225
226
227
	/**
	 * Array of tables to be listed by the Web > Page module in addition to the default tables
	 *
	 * @var array
	 */
228
229
	public $externalTables = array();

230
231
232
233
234
	/**
	 * Module output accumulation
	 *
	 * @var string
	 */
235
236
	public $content;

237
238
239
240
241
	/**
	 * Function menu temporary storage
	 *
	 * @var string
	 */
242
243
	public $topFuncMenu;

244
245
246
247
248
249
250
251
	/**
	 * List of column-integers accessible to the current BE user.
	 * Is set from TSconfig, default is $colPosList
	 *
	 * @var string
	 */
	public $activeColPosList;

252
	/**
253
254
255
	 * Markers array
	 *
	 * @var array
256
257
258
	 */
	protected $markers = array();

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	/**
	 * @var array
	 */
	protected $eRParts = array();

	/**
	 * @var string
	 */
	protected $editSelect;

	/**
	 * @var bool
	 */
	protected $deleteButton;

	/**
	 * @var bool
	 */
	protected $undoButton;

	/**
	 * @var array
	 */
	protected $undoButtonR;

	/**
	 * @var string
	 */
	protected $R_URI;

	/**
	 * @var string
	 */
	protected $closeUrl;

294
295
296
297
298
299
	/**
	 * Initializing the module
	 *
	 * @return void
	 */
	public function init() {
Wouter Wolters's avatar
Wouter Wolters committed
300
		$this->getLanguageService()->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
301

302
303
		// Setting module configuration / page select clause
		$this->MCONF = $GLOBALS['MCONF'];
304
		$this->perms_clause = $this->getBackendUser()->getPagePermsClause(1);
305
		$this->backPath = $GLOBALS['BACK_PATH'];
306
		// Get session data
307
		$sessionData = $this->getBackendUser()->getSessionData(RecordList::class);
308
		$this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
309
		// GPvars:
310
		$this->id = (int)GeneralUtility::_GP('id');
Nicole Cordes's avatar
Nicole Cordes committed
311
312
313
314
315
		$this->pointer = GeneralUtility::_GP('pointer');
		$this->imagemode = GeneralUtility::_GP('imagemode');
		$this->clear_cache = GeneralUtility::_GP('clear_cache');
		$this->popView = GeneralUtility::_GP('popView');
		$this->edit_record = GeneralUtility::_GP('edit_record');
316
		$this->new_unique_uid = GeneralUtility::_GP('new_unique_uid');
317
		$this->search_field = GeneralUtility::_GP('search_field');
Nicole Cordes's avatar
Nicole Cordes committed
318
319
320
		$this->search_levels = GeneralUtility::_GP('search_levels');
		$this->showLimit = GeneralUtility::_GP('showLimit');
		$this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
321
		$this->externalTables = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['cms']['db_layout']['addTables'];
322
		$sessionData['search_field'] = $this->search_field;
323
		// Store session data
324
		$this->getBackendUser()->setAndSaveSessionData(RecordList::class, $sessionData);
325
		// Load page info array:
Nicole Cordes's avatar
Nicole Cordes committed
326
		$this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
327
328
329
		// Initialize menu
		$this->menuConfig();
		// Setting sys language from session var:
330
		$this->current_sys_language = (int)$this->MOD_SETTINGS['language'];
331
332
		// CSH / Descriptions:
		$this->descrTable = '_MOD_' . $this->MCONF['name'];
333
334
335

		$this->markers['SEARCHBOX'] = '';
		$this->markers['BUTTONLIST_ADDITIONAL'] = '';
336
337
338
339
340
341
342
343
	}

	/**
	 * Initialize menu array
	 *
	 * @return void
	 */
	public function menuConfig() {
344
		$lang = $this->getLanguageService();
345
346
347
348
		// MENU-ITEMS:
		$this->MOD_MENU = array(
			'tt_content_showHidden' => '',
			'function' => array(
349
350
351
				0 => $lang->getLL('m_function_0'),
				1 => $lang->getLL('m_function_1'),
				2 => $lang->getLL('m_function_2')
352
353
			),
			'language' => array(
354
				0 => $lang->getLL('m_default')
355
356
357
358
359
			)
		);
		// example settings:
		// 	$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['cms']['db_layout']['addTables']['tx_myext'] =
		//		array ('default' => array(
360
		//				'MENU' => 'LLL:EXT:tx_myext/locallang_db.xlf:menuDefault',
361
362
363
364
365
366
367
368
369
370
		//				'fList' =>  'title,description,image',
		//				'icon' => TRUE));
		if (is_array($this->externalTables)) {
			foreach ($this->externalTables as $table => $tableSettings) {
				// delete the default settings from above
				if (is_array($this->MOD_MENU[$table])) {
					unset($this->MOD_MENU[$table]);
				}
				if (is_array($tableSettings) && count($tableSettings) > 1) {
					foreach ($tableSettings as $key => $settings) {
371
						$this->MOD_MENU[$table][$key] = $lang->sL($settings['MENU']);
372
373
374
375
376
377
					}
				}
			}
		}
		// First, select all pages_language_overlay records on the current page. Each represents a possibility for a language on the page. Add these to language selector.
		$res = $this->exec_languageQuery($this->id);
378
379
380
		while ($lRow = $this->getDatabaseConnection()->sql_fetch_assoc($res)) {
			if ($this->getBackendUser()->checkLanguageAccess($lRow['uid'])) {
				$this->MOD_MENU['language'][$lRow['uid']] = $lRow['hidden'] ? '(' . $lRow['title'] . ')' : $lRow['title'];
381
382
383
			}
		}
		// Find if there are ANY languages at all (and if not, remove the language option from function menu).
384
		$count = $this->getDatabaseConnection()->exec_SELECTcountRows('uid', 'sys_language', $this->getBackendUser()->isAdmin() ? '' : 'hidden=0');
385
386
387
388
		if (!$count) {
			unset($this->MOD_MENU['function']['2']);
		}
		// page/be_user TSconfig settings and blinding of menu-items
Nicole Cordes's avatar
Nicole Cordes committed
389
390
		$this->modSharedTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.SHARED');
		$this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->MCONF['name']);
391
392
393
		if ($this->modTSconfig['properties']['QEisDefault']) {
			ksort($this->MOD_MENU['function']);
		}
Nicole Cordes's avatar
Nicole Cordes committed
394
		$this->MOD_MENU['function'] = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $this->MOD_MENU['function'], 'menu.function');
395
		// Remove QuickEdit as option if page type is not...
396
		if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'] . ',6', $this->pageinfo['doktype'])) {
397
398
399
400
401
402
403
			unset($this->MOD_MENU['function'][0]);
		}
		// Setting alternative default label:
		if (($this->modSharedTSconfig['properties']['defaultLanguageLabel'] || $this->modTSconfig['properties']['defaultLanguageLabel']) && isset($this->MOD_MENU['language'][0])) {
			$this->MOD_MENU['language'][0] = $this->modTSconfig['properties']['defaultLanguageLabel'] ? $this->modSharedTSconfig['properties']['defaultLanguageLabel'] : $this->modSharedTSconfig['properties']['defaultLanguageLabel'];
		}
		// Clean up settings
404
		$this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_layout');
405
		// For all elements to be shown in draft workspaces & to also show hidden elements by default if user hasn't disabled the option
406
		if ($this->getBackendUser()->workspace != 0 || $this->MOD_SETTINGS['tt_content_showHidden'] !== '0') {
407
408
409
410
411
412
413
414
415
416
417
			$this->MOD_SETTINGS['tt_content_showHidden'] = 1;
		}
	}

	/**
	 * Clears page cache for the current id, $this->id
	 *
	 * @return void
	 */
	public function clearCache() {
		if ($this->clear_cache) {
418
419
			$tce = GeneralUtility::makeInstance(DataHandler::class);
			$tce->stripslashes_values = FALSE;
420
421
422
423
424
425
426
427
428
429
430
431
			$tce->start(array(), array());
			$tce->clear_cacheCmd($this->id);
		}
	}

	/**
	 * Generate the flashmessages for current pid
	 *
	 * @return string HTML content with flashmessages
	 */
	protected function getHeaderFlashMessagesForCurrentPid() {
		$content = '';
432
		$lang = $this->getLanguageService();
433
		// If page is a folder
434
		if ($this->pageinfo['doktype'] == PageRepository::DOKTYPE_SYSFOLDER) {
435
			// Access to list module
436
			$moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
437
438
439
			$moduleLoader->load($GLOBALS['TBE_MODULES']);
			$modules = $moduleLoader->modules;
			if (is_array($modules['web']['sub']['list'])) {
440
441
442
				$title = $lang->getLL('goToListModule');
				$message = '<p>' . $lang->getLL('goToListModuleMessage') . '</p>';
				$message .= '<a class="btn btn-info" href="javascript:top.goToModule(\'web_list\',1);">' . $lang->getLL('goToListModule') . '</a>';
443
444
445
446

				$view = GeneralUtility::makeInstance(StandaloneView::class);
				$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
				$view->assignMultiple(array(
447
448
					'title' => $title,
					'message' => $message,
449
450
451
					'state' => InfoboxViewHelper::STATE_INFO
				));
				$content .= $view->render();
452
453
454
455
			}
		}
		// If content from different pid is displayed
		if ($this->pageinfo['content_from_pid']) {
456
			$contentPage = BackendUtility::getRecord('pages', (int)$this->pageinfo['content_from_pid']);
Nicole Cordes's avatar
Nicole Cordes committed
457
			$title = BackendUtility::getRecordTitle('pages', $contentPage);
458
			$linkToPid = $this->local_linkThisScript(array('id' => $this->pageinfo['content_from_pid']));
459
			$link = '<a href="' . $linkToPid . '">' . htmlspecialchars($title) . ' (PID ' . (int)$this->pageinfo['content_from_pid'] . ')</a>';
460
			$flashMessage = GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('content_from_pid_title'), $link), '', FlashMessage::INFO);
461
462
463
464
465
			$content .= $flashMessage->render();
		}
		return $content;
	}

466
467
468
469
470
471
	/**
	 *
	 * @return string $title
	 */
	protected function getLocalizedPageTitle() {
		if ($this->current_sys_language > 0) {
472
			$overlayRecord = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
473
474
				'title',
				'pages_language_overlay',
475
476
				'pid = ' . (int)$this->id .
						' AND sys_language_uid = ' . (int)$this->current_sys_language .
Nicole Cordes's avatar
Nicole Cordes committed
477
478
						BackendUtility::deleteClause('pages_language_overlay') .
						BackendUtility::versioningPlaceholderClause('pages_language_overlay'),
479
480
481
482
483
484
485
486
487
488
489
				'',
				'',
				'',
				'sys_language_uid'
			);
			return $overlayRecord['title'];
		} else {
			return $this->pageinfo['title'];
		}
	}

490
491
492
493
494
495
496
	/**
	 * Main function.
	 * Creates some general objects and calls other functions for the main rendering of module content.
	 *
	 * @return void
	 */
	public function main() {
497
		$lang = $this->getLanguageService();
498
499
500
501
502
		// Access check...
		// The page will show only if there is a valid page and if this page may be viewed by the user
		$access = is_array($this->pageinfo) ? 1 : 0;
		if ($this->id && $access) {
			// Initialize permission settings:
503
			$this->CALC_PERMS = $this->getBackendUser()->calcPerms($this->pageinfo);
504
			$this->EDIT_CONTENT = $this->CALC_PERMS & Permission::CONTENT_EDIT ? 1 : 0;
505
			// Start document template object:
506
			$this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
507
			$this->doc->backPath = $GLOBALS['BACK_PATH'];
508
			$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout.html');
509
510
511
512

			// override the default jumpToUrl
			$this->doc->JScodeArray['jumpToUrl'] = '
				function jumpToUrl(URL,formEl) {
513
					if (document.editform && TBE_EDITOR.isFormChanged)	{	// Check if the function exists... (works in all browsers?)
514
						if (!TBE_EDITOR.isFormChanged()) {
515
516
517
518
							window.location.href = URL;
						} else if (formEl) {
							if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
						}
519
520
521
					} else {
						window.location.href = URL;
					}
522
				}
523
524
525
526
527
';

			$this->doc->JScode .= $this->doc->wrapScriptTags('
				if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
				if (top.fsMod) top.fsMod.navFrameHighlightedID["web"] = "pages' . (int)$this->id . '_"+top.fsMod.currentBank; ' . (int)$this->id . ';
Nicole Cordes's avatar
Nicole Cordes committed
528
			' . ($this->popView ? BackendUtility::viewOnClick($this->id, $GLOBALS['BACK_PATH'], BackendUtility::BEgetRootLine($this->id)) : '') . '
529
530

				function deleteRecord(table,id,url) {	//
531
532
					if (confirm(' . GeneralUtility::quoteJSvalue($lang->getLL('deleteWarning')) . ')) {
						window.location.href = ' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&cmd[') . '+table+"]["+id+"][delete]=1&redirect="+escape(url)+"&vC=' . $this->getBackendUser()->veriCode() . BackendUtility::getUrlToken('tceAction') . '&prErr=1&uPT=1";
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
					}
					return false;
				}
			');
			$this->doc->JScode .= $this->doc->wrapScriptTags('
				var DTM_array = new Array();
				var DTM_origClass = new String();

					// if tabs are used in a popup window the array might not exists
				if(!top.DTM_currentTabs) {
					top.DTM_currentTabs = new Array();
				}

				function DTM_activate(idBase,index,doToogle) {	//
						// Hiding all:
					if (DTM_array[idBase]) {
						for(cnt = 0; cnt < DTM_array[idBase].length ; cnt++) {
							if (DTM_array[idBase][cnt] != idBase+"-"+index) {
Benjamin Kott's avatar
Benjamin Kott committed
551
552
								document.getElementById(DTM_array[idBase][cnt]+"-DIV").className = "tab-pane";
								document.getElementById(DTM_array[idBase][cnt]+"-MENU").attributes.getNamedItem("class").value = "tab";
553
554
555
556
557
558
							}
						}
					}

						// Showing one:
					if (document.getElementById(idBase+"-"+index+"-DIV")) {
Benjamin Kott's avatar
Benjamin Kott committed
559
560
						if (doToogle && document.getElementById(idBase+"-"+index+"-DIV").className === "tab-pane active") {
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane";
561
							if(DTM_origClass=="") {
Benjamin Kott's avatar
Benjamin Kott committed
562
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "tab";
563
564
565
566
567
							} else {
								DTM_origClass = "tab";
							}
							top.DTM_currentTabs[idBase] = -1;
						} else {
Benjamin Kott's avatar
Benjamin Kott committed
568
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane active";
569
							if(DTM_origClass=="") {
Benjamin Kott's avatar
Benjamin Kott committed
570
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "active";
571
							} else {
572
								DTM_origClass = "active";
573
574
575
576
577
578
579
580
581
							}
							top.DTM_currentTabs[idBase] = index;
						}
					}
				}
				function DTM_toggle(idBase,index,isInit) {	//
						// Showing one:
					if (document.getElementById(idBase+"-"+index+"-DIV")) {
						if (document.getElementById(idBase+"-"+index+"-DIV").style.display == "block") {
Benjamin Kott's avatar
Benjamin Kott committed
582
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane";
583
							if(isInit) {
Benjamin Kott's avatar
Benjamin Kott committed
584
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "tab";
585
586
587
588
589
							} else {
								DTM_origClass = "tab";
							}
							top.DTM_currentTabs[idBase+"-"+index] = 0;
						} else {
Benjamin Kott's avatar
Benjamin Kott committed
590
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane active";
591
							if(isInit) {
Benjamin Kott's avatar
Benjamin Kott committed
592
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "active";
593
							} else {
594
								DTM_origClass = "active";
595
596
597
598
599
600
601
							}
							top.DTM_currentTabs[idBase+"-"+index] = 1;
						}
					}
				}
			');
			// Setting doc-header
602
603
604
605
			$this->doc->form = '<form action="' . htmlspecialchars(
				BackendUtility::getModuleUrl(
					'web_layout', array('id' => $this->id, 'imagemode' =>  $this->imagemode)
				)) . '" method="post">';
606
			// Creating the top function menu:
607
			$this->topFuncMenu = BackendUtility::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function'], '', '');
608
			$languageMenu = count($this->MOD_MENU['language']) > 1 ? $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.language', TRUE) . BackendUtility::getFuncMenu($this->id, 'SET[language]', $this->current_sys_language, $this->MOD_MENU['language'], '', '') : '';
609
			// Find backend layout / coumns
610
			$backendLayout = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getSelectedBackendLayout', $this->id, $this);
611
			if (!empty($backendLayout['__colPosList'])) {
612
613
614
				$this->colPosList = implode(',', $backendLayout['__colPosList']);
			}
			// Removing duplicates, if any
615
616
			$this->colPosList = array_unique(GeneralUtility::intExplode(',', $this->colPosList));
			// Accessible columns
617
			if (isset($this->modSharedTSconfig['properties']['colPos_list']) && trim($this->modSharedTSconfig['properties']['colPos_list']) !== '') {
618
619
				$this->activeColPosList = array_unique(GeneralUtility::intExplode(',', trim($this->modSharedTSconfig['properties']['colPos_list'])));
				// Match with the list which is present in the colPosList for the current page
620
621
				if (!empty($this->colPosList) && !empty($this->activeColPosList)) {
					$this->activeColPosList = array_unique(array_intersect(
622
623
						$this->activeColPosList,
						$this->colPosList
624
					));
625
				}
626
627
			} else {
				$this->activeColPosList = $this->colPosList;
628
			}
629
			$this->activeColPosList = implode(',', $this->activeColPosList);
630
631
			$this->colPosList = implode(',', $this->colPosList);

632
			$body = '';
633
634
635
636
637
638
			$body .= $this->getHeaderFlashMessagesForCurrentPid();
			// Render the primary module content:
			if ($this->MOD_SETTINGS['function'] == 0) {
				// QuickEdit
				$body .= $this->renderQuickEdit();
			} else {
639
640
				// Page title
				$body .= $this->doc->header($this->getLocalizedPageTitle());
641
642
643
644
645
				// All other listings
				$body .= $this->renderListContent();
			}
			// Setting up the buttons and markers for docheader
			$docHeaderButtons = $this->getButtons($this->MOD_SETTINGS['function'] == 0 ? 'quickEdit' : '');
646
647
			$this->markers['CSH'] = $docHeaderButtons['csh'];
			$this->markers['TOP_FUNCTION_MENU'] = $this->topFuncMenu . $this->editSelect;
648
			$this->markers['LANGSELECTOR'] = $languageMenu;
649
			$this->markers['CONTENT'] = $body;
650
			// Build the <body> for the module
651
			$this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $this->markers);
652
			// Renders the module page
653
			$this->content = $this->doc->render($lang->getLL('title'), $this->content);
654
655
		} else {
			// If no access or id value, create empty document:
656
			$this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
657
			$this->doc->backPath = $GLOBALS['BACK_PATH'];
658
			$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout.html');
659
			$this->doc->JScode = $this->doc->wrapScriptTags('
660
				if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
661
			');
662
663

			$body = $this->doc->header($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']);
664

665
666
			$title = $lang->getLL('clickAPage_header');
			$message = $lang->getLL('clickAPage_content');
667
668
669
670

			$view = GeneralUtility::makeInstance(StandaloneView::class);
			$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
			$view->assignMultiple(array(
671
672
				'title' => $title,
				'message' => $message,
673
674
675
				'state' => InfoboxViewHelper::STATE_INFO
			));
			$body .= $view->render();
676

677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
			// Setting up the buttons and markers for docheader
			$docHeaderButtons = array(
				'view' => '',
				'history_page' => '',
				'new_content' => '',
				'move_page' => '',
				'move_record' => '',
				'new_page' => '',
				'edit_page' => '',
				'csh' => '',
				'shortcut' => '',
				'cache' => '',
				'savedok' => '',
				'savedokshow' => '',
				'closedok' => '',
				'deletedok' => '',
				'undo' => '',
694
695
				'history_record' => '',
				'edit_language' => ''
696
			);
Benni Mack's avatar
Benni Mack committed
697
			$this->markers['CSH'] = '';
698
699
700
701
			$this->markers['TOP_FUNCTION_MENU'] = '';
			$this->markers['LANGSELECTOR'] = '';
			$this->markers['CONTENT'] = $body;
			$this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $this->markers);
702
			// Renders the module page
703
			$this->content = $this->doc->render($lang->getLL('title'), $this->content);
704
705
706
707
708
709
		}
	}

	/**
	 * Rendering the quick-edit view.
	 *
710
	 * @return string
711
712
	 */
	public function renderQuickEdit() {
713
714
715
		$databaseConnection = $this->getDatabaseConnection();
		$beUser = $this->getBackendUser();
		$lang = $this->getLanguageService();
716
		// Alternative template
717
		$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout_quickedit.html');
718
		// Alternative form tag; Quick Edit submits its content to tce_db.php.
719
		$this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
720
721
722
723
		// Setting up the context sensitive menu:
		$this->doc->getContextMenuCode();
		// Set the edit_record value for internal use in this function:
		$edit_record = $this->edit_record;
724
		// If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine
725
		if (substr($edit_record, 0, 9) == '_EDIT_COL') {
726
			$res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$this->id . ' AND colPos=' . (int)substr($edit_record, 10) . ' AND sys_language_uid=' . (int)$this->current_sys_language . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting');
727
			$idListA = array();
728
			while ($cRow = $databaseConnection->sql_fetch_assoc($res)) {
729
730
				$idListA[] = $cRow['uid'];
			}
731
732
			$url = BackendUtility::getModuleUrl('record_edit', array(
				'edit[tt_content][' . implode(',', $idListA) . ']' => 'edit',
733
				'returnUrl' => $this->local_linkThisScript(array('edit_record' => ''))
734
			));
735
			HttpUtility::redirect($url);
736
		}
737
738
		// If the former record edited was the creation of a NEW record, this will look up the created records uid:
		if ($this->new_unique_uid) {
739
740
			$res = $databaseConnection->exec_SELECTquery('*', 'sys_log', 'userid=' . (int)$beUser->user['uid'] . ' AND NEWid=' . $databaseConnection->fullQuoteStr($this->new_unique_uid, 'sys_log'));
			$sys_log_row = $databaseConnection->sql_fetch_assoc($res);
741
742
743
744
			if (is_array($sys_log_row)) {
				$edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid'];
			}
		}
745
746
747
748
749
		// Creating the selector box, allowing the user to select which element to edit:
		$opt = array();
		$is_selected = 0;
		$languageOverlayRecord = '';
		if ($this->current_sys_language) {
750
			list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int)$this->current_sys_language);
751
752
753
		}
		if (is_array($languageOverlayRecord)) {
			$inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid'];
754
			$is_selected += (int)$edit_record == $inValue;
755
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editLanguageHeader', TRUE) . ' ]</option>';
756
757
		} else {
			$inValue = 'pages:' . $this->id;
758
			$is_selected += (int)$edit_record == $inValue;
759
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editPageProperties', TRUE) . ' ]</option>';
760
761
		}
		// Selecting all content elements from this language and allowed colPos:
762
		$res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$this->id . ' AND sys_language_uid=' . (int)$this->current_sys_language . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting');
763
		$colPos = NULL;
764
765
766
		$first = 1;
		// Page is the pid if no record to put this after.
		$prev = $this->id;
767
		while ($cRow = $databaseConnection->sql_fetch_assoc($res)) {
Nicole Cordes's avatar
Nicole Cordes committed
768
			BackendUtility::workspaceOL('tt_content', $cRow);
769
770
771
772
773
774
775
			if (is_array($cRow)) {
				if ($first) {
					if (!$edit_record) {
						$edit_record = 'tt_content:' . $cRow['uid'];
					}
					$first = 0;
				}
776
				if (!isset($colPos) || $cRow['colPos'] !== $colPos) {
777
778
					$colPos = $cRow['colPos'];
					$opt[] = '<option value=""></option>';
779
					$opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), TRUE) . ':__</option>';
780
781
				}
				$inValue = 'tt_content:' . $cRow['uid'];
782
				$is_selected += (int)$edit_record == $inValue;
783
				$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext'])), $beUser->uc['titleLen'])) . '</option>';
784
785
786
787
788
				$prev = -$cRow['uid'];
			}
		}
		// If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element:
		if (!$edit_record) {
789
790
			$edit_record = 'tt_content:new/' . $prev . '/' . $colPos;
			$inValue = 'tt_content:new/' . $prev . '/' . $colPos;
791
			$is_selected += (int)$edit_record == $inValue;
792
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('newLabel', 1) . ' ]</option>';
793
794
795
796
		}
		// If none is yet selected...
		if (!$is_selected) {
			$opt[] = '<option value=""></option>';
797
			$opt[] = '<option value="' . $edit_record . '"  selected="selected">[ ' . $lang->getLL('newLabel', TRUE) . ' ]</option>';
798
799
800
801
		}
		// Splitting the edit-record cmd value into table/uid:
		$this->eRParts = explode(':', $edit_record);
		// Delete-button flag?
802
		$this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($this->eRParts[0] != 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] == 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE);
803
		// If undo-button should be rendered (depends on available items in sys_history)
804
805
806
807
		$this->undoButton = FALSE;
		$undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($this->eRParts[0], 'sys_history') . ' AND recuid=' . (int)$this->eRParts[1], '', 'tstamp DESC', '1');
		if ($this->undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) {
			$this->undoButton = TRUE;
808
809
		}
		// Setting up the Return URL for coming back to THIS script (if links take the user to another script)
Nicole Cordes's avatar
Nicole Cordes committed
810
811
		$R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
		$R_URL_getvars = GeneralUtility::_GET();
812
		unset($R_URL_getvars['popView']);
813
		unset($R_URL_getvars['new_unique_uid']);
814
		$R_URL_getvars['edit_record'] = $edit_record;
Nicole Cordes's avatar
Nicole Cordes committed
815
		$this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars);
816
817
818
819
820
821
822
		// Setting close url/return url for exiting this script:
		// Goes to 'Columns' view if close is pressed (default)
		$this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1)));
		if ($this->returnUrl) {
			$this->closeUrl = $this->returnUrl;
		}
		// Return-url for JavaScript:
823
		$retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+' . GeneralUtility::quoteJSvalue(rawurlencode($this->returnUrl)) : '';
824
		// Drawing the edit record selectbox
825
826
827
		$this->editSelect = '<select name="edit_record" onchange="' . htmlspecialchars('jumpToUrl(' . GeneralUtility::quoteJSvalue(
			BackendUtility::getModuleUrl('web_layout') . '&id=' . $this->id . '&edit_record='
		) . '+escape(this.options[this.selectedIndex].value)' . $retUrlStr . ',this);') . '">' . implode('', $opt) . '</select>';
828
		$content = '';
829
		// Creating editing form:
830
		if ($beUser->check('tables_modify', $this->eRParts[0]) && $edit_record && ($this->eRParts[0] !== 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] === 'pages' && $this->CALC_PERMS & Permission::PAGE_SHOW)) {
831
832
833
834
			// Splitting uid parts for special features, if new:
			list($uidVal, $ex_pid, $ex_colPos) = explode('/', $this->eRParts[1]);
			// Convert $uidVal to workspace version if any:
			if ($uidVal != 'new') {
835
				if ($draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $this->eRParts[0], $uidVal, 'uid')) {
836
837
838
839
					$uidVal = $draftRecord['uid'];
				}
			}
			// Initializing transfer-data object:
840
			$trData = GeneralUtility::makeInstance(DataPreprocessor::class);
841
842
			$trData->addRawData = TRUE;
			$trData->defVals[$this->eRParts[0]] = array(
843
844
				'colPos' => (int)$ex_colPos,
				'sys_language_uid' => (int)$this->current_sys_language
845
846
847
848
			);
			$trData->lockRecords = 1;
			// 'new'
			$trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal);
849
			$new_unique_uid = '';
850
851
852
853
			// Getting/Making the record:
			reset($trData->regTableItems_data);
			$rec = current($trData->regTableItems_data);
			if ($uidVal == 'new') {
854
				$new_unique_uid = uniqid('NEW', TRUE);
855
				$rec['uid'] = $new_unique_uid;
856
				$rec['pid'] = (int)$ex_pid ?: $this->id;
857
858
859
860
				$recordAccess = TRUE;
			} else {
				$rec['uid'] = $uidVal;
				// Checking internals access:
861
				$recordAccess = $beUser->recordEditAccessInternals($this->eRParts[0], $uidVal);
862
863
864
			}
			if (!$recordAccess) {
				// If no edit access, print error message:
865
				$content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : ''), 0, 1);
866
867
868
			} elseif (is_array($rec)) {
				// If the record is an array (which it will always be... :-)
				// Create instance of TCEforms, setting defaults:
869
				$tceForms = GeneralUtility::makeInstance(FormEngine::class);
870
871
				// Render form, wrap it:
				$panel = '';
872
873
				$panel .= $tceForms->getMainFields($this->eRParts[0], $rec);
				$panel = $tceForms->wrapTotal($panel, $rec, $this->eRParts[0]);
874
875
876
				// Add hidden fields:
				$theCode = $panel;
				if ($uidVal == 'new') {
877
					$theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />';
878
				}
879
880
881
				$theCode .= '
					<input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />
					<input type="hidden" name="edit_record" value="' . $edit_record . '" />
882
883
884
885
886
887
888
889
					<input type="hidden" name="redirect" value="' . htmlspecialchars(($uidVal == 'new' ? BackendUtility::getModuleUrl(
						'web_layout',
						array(
							'id' => $this->id,
							'new_unique_uid' => $new_unique_uid,
							'returnUrl' => $this->returnUrl
						)
					) : $this->R_URI)) . '" />
890
					' . FormEngine::getHiddenTokenField('tceAction');
891
				// Add JavaScript as needed around the form:
892
				$theCode = $tceForms->printNeededJSFunctions_top() . $theCode . $tceForms->printNeededJSFunctions();
893
				// Add warning sign if record was "locked":
Nicole Cordes's avatar
Nicole Cordes committed
894
				if ($lockInfo = BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) {
895
896
					/** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
					$flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING);
897
					/** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
898
					$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
899
900
901
					/** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
					$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
					$defaultFlashMessageQueue->enqueue($flashMessage);
902
903
				}
				// Add whole form as a document section:
904
				$content = $this->doc->section('', $theCode);
905
906
907
			}
		} else {
			// If no edit access, print error message:
908
			$content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />', 0, 1);
909
910
911
		}
		// Bottom controls (function menus):
		$q_count = $this->getNumberOfHiddenElements();
912
913
914
915
916
917
918
919
920
921
922
		if ($q_count) {
			$h_func_b = '<div class="checkbox">' .
				'<label for="checkTt_content_showHidden">' .
				BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"') .
				(!$q_count ? ('<span class="text-muted">' . $lang->getLL('hiddenCE', TRUE) . '</span>') : $lang->getLL('hiddenCE', TRUE) . ' (' . $q_count . ')') .
				'</label>' .
				'</div>';

			$content .= $this->doc->section('', $h_func_b, 0, 0);
			$content .= $this->doc->spacer(10);
		}
923

924
		// Select element matrix:
Nicole Cordes's avatar
Nicole Cordes committed
925
		if ($this->eRParts[0] == 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
926
			$posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class);
927
928
929
930
			$posMap->backPath = $GLOBALS['BACK_PATH'];
			$posMap->cur_sys_language = $this->current_sys_language;
			$HTMLcode = '';
			// CSH:
Benni Mack's avatar
Benni Mack committed
931
			$HTMLcode .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', NULL, '|<br />');
932
933
			$HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI);
			$content .= $this->doc->spacer(20);
934
			$content .= $this->doc->section($lang->getLL('CEonThisPage'), $HTMLcode, 0, 1);
935
936
937
938
939
940
941
942
			$content .= $this->doc->spacer(20);
		}
		return $content;
	}

	/**
	 * Rendering all other listings than QuickEdit
	 *
943
	 * @return string
944
945
	 */
	public function renderListContent() {
946
947
948
949
950
951
		/** @var $dbList \TYPO3\CMS\Backend\View\PageLayoutView */
		$dbList = GeneralUtility::makeInstance(PageLayoutView::class);
		$dbList->backPath = $GLOBALS['BACK_PATH'];
		$dbList->thumbs = $this->imagemode;
		$dbList->no_noWrap = 1;
		$dbList->descrTable = $this->descrTable;
Nicole Cordes's avatar
Nicole Cordes committed
952
		$this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
953
954
955
956
957
958
959
960
961
962
963
964
		$dbList->script = BackendUtility::getModuleUrl('web_layout');
		$dbList->showIcon = 0;
		$dbList->setLMargin = 0;
		$dbList->doEdit = $this->EDIT_CONTENT;
		$dbList->ext_CALC_PERMS = $this->CALC_PERMS;
		$dbList->agePrefixes = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears');
		$dbList->id = $this->id;
		$dbList->nextThree = MathUtility::forceIntegerInRange($this->modTSconfig['properties']['editFieldsAtATime'], 0, 10);
		$dbList->option_newWizard = $this->modTSconfig['properties']['disableNewContentElementWizard'] ? 0 : 1;
		$dbList->defLangBinding = $this->modTSconfig['properties']['defLangBinding'] ? 1 : 0;
		if (!$dbList->nextThree) {
			$dbList->nextThree = 1;
965
		}
966
		$dbList->externalTables = $this->externalTables;
967
		// Create menu for selecting a table to jump to (this is, if more than just pages/tt_content elements are found on the page!)
968
969
		// also fills $dbList->activeTables
		$dbList->getTableMenu($this->id);
970
971
972
973
974
975
976
		// Initialize other variables:
		$h_func = '';
		$tableOutput = array();
		$tableJSOutput = array();
		$CMcounter = 0;
		// Traverse the list of table names which has records on this page (that array is populated
		// by the $dblist object during the function getTableMenu()):
977
978
979
		foreach ($dbList->activeTables as $table => $value) {
			$h_func_b = '';
			if (!isset($dbList->externalTables[$table])) {
980
				$q_count = $this->getNumberOfHiddenElements();
981

982
983
984
				if ($q_count > 0) {
					$h_func_b =
						'<div class="checkbox">'
985
						. '<label for="checkTt_content_showHidden">'
986
987
						. '<input type="checkbox" id="checkTt_content_showHidden" class="checkbox" name="SET[tt_content_showHidden]" value="1" ' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? 'checked="checked"' : '') . ' />'
						. $this->getLanguageService()->getLL('hiddenCE', TRUE) . ' (<span class="t3js-hidden-counter">' . $q_count . '</span>)'
988
						. '</label>'
989
990
						. '</div>';
				}
991
				// Boolean: Display up/down arrows and edit icons for tt_content records
992
				$dbList->tt_contentConfig['showCommands'] = 1;
993
				// Boolean: Display info-marks or not
994
				$dbList->tt_contentConfig['showInfo'] = 1;
995
996
997
				// Setting up the tt_content columns to show:
				if (is_array($GLOBALS['TCA']['tt_content']['columns']['colPos']['config']['items'])) {
					$colList = array();
998
					$tcaItems = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getColPosListItemsParsed', $this->id, $this);
999
1000
					foreach ($tcaItems as $temp) {
						$colList[] = $temp[1];