PageLayoutController.php 56 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
20
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
21
use TYPO3\CMS\Core\Type\Bitmask\Permission;
Nicole Cordes's avatar
Nicole Cordes committed
22
23
24
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
use TYPO3\CMS\Core\Utility\HttpUtility;
Nicole Cordes's avatar
Nicole Cordes committed
26
use TYPO3\CMS\Core\Utility\MathUtility;
27
use TYPO3\CMS\Fluid\View\StandaloneView;
28
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
29
30
31
32
33
34
35
36
37
38
39
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;
40
use TYPO3\CMS\Core\Versioning\VersionState;
Nicole Cordes's avatar
Nicole Cordes committed
41

42
43
44
45
46
/**
 * Script Class for Web > Layout module
 */
class PageLayoutController {

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

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

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

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

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

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

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

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

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

110
111
112
113
114
115
	/**
	 * 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
	 */
116
117
	public $edit_record;

118
119
120
121
122
123
124
125
	/**
	 * 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;

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

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

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

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

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

161
162
163
164
165
	/**
	 * "Pseudo" Description -table name
	 *
	 * @var string
	 */
166
167
	public $descrTable;

168
169
170
171
172
	/**
	 * List of column-integers to edit. Is set from TSconfig, default is "1,0,2,3"
	 *
	 * @var string
	 */
173
174
	public $colPosList;

175
176
177
178
179
	/**
	 * Flag: If content can be edited or not.
	 *
	 * @var bool
	 */
180
181
	public $EDIT_CONTENT;

182
183
184
185
186
	/**
	 * Users permissions integer for this page.
	 *
	 * @var int
	 */
187
188
	public $CALC_PERMS;

189
190
191
192
193
	/**
	 * Currently selected language for editing content elements
	 *
	 * @var int
	 */
194
195
	public $current_sys_language;

196
197
198
199
200
	/**
	 * Module configuration
	 *
	 * @var array
	 */
201
202
	public $MCONF = array();

203
204
205
206
207
	/**
	 * Menu configuration
	 *
	 * @var array
	 */
208
209
	public $MOD_MENU = array();

210
211
212
213
214
	/**
	 * Module settings (session variable)
	 *
	 * @var array
	 */
215
216
	public $MOD_SETTINGS = array();

217
218
219
220
221
	/**
	 * Array of tables to be listed by the Web > Page module in addition to the default tables
	 *
	 * @var array
	 */
222
223
	public $externalTables = array();

224
225
226
227
228
	/**
	 * Module output accumulation
	 *
	 * @var string
	 */
229
230
	public $content;

231
232
233
234
235
	/**
	 * Function menu temporary storage
	 *
	 * @var string
	 */
236
237
	public $topFuncMenu;

238
239
240
241
242
243
244
245
	/**
	 * List of column-integers accessible to the current BE user.
	 * Is set from TSconfig, default is $colPosList
	 *
	 * @var string
	 */
	public $activeColPosList;

246
	/**
247
248
249
	 * Markers array
	 *
	 * @var array
250
251
252
	 */
	protected $markers = array();

253
254
255
256
257
258
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
	/**
	 * @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;

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
	/**
	 * Caches the available languages in a colPos
	 *
	 * @var array
	 */
	protected $languagesInColumnCache = array();

	/**
	 * Caches the amount of content elements as a matrix
	 *
	 * @var array
	 * @internal
	 */
	public $contentElementCache = array();

303
304
305
306
307
	/**
	 * @var IconFactory
	 */
	protected $iconFactory;

308
309
310
311
312
313
	/**
	 * Initializing the module
	 *
	 * @return void
	 */
	public function init() {
314
		$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
Wouter Wolters's avatar
Wouter Wolters committed
315
		$this->getLanguageService()->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
316

317
318
		// Setting module configuration / page select clause
		$this->MCONF = $GLOBALS['MCONF'];
319
		$this->perms_clause = $this->getBackendUser()->getPagePermsClause(1);
320
		// Get session data
321
		$sessionData = $this->getBackendUser()->getSessionData(RecordList::class);
322
		$this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
323
		// GPvars:
324
		$this->id = (int)GeneralUtility::_GP('id');
Nicole Cordes's avatar
Nicole Cordes committed
325
326
327
328
329
		$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');
330
		$this->new_unique_uid = GeneralUtility::_GP('new_unique_uid');
331
		$this->search_field = GeneralUtility::_GP('search_field');
Nicole Cordes's avatar
Nicole Cordes committed
332
333
334
		$this->search_levels = GeneralUtility::_GP('search_levels');
		$this->showLimit = GeneralUtility::_GP('showLimit');
		$this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
335
		$this->externalTables = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['cms']['db_layout']['addTables'];
336
		$sessionData['search_field'] = $this->search_field;
337
		// Store session data
338
		$this->getBackendUser()->setAndSaveSessionData(RecordList::class, $sessionData);
339
		// Load page info array:
Nicole Cordes's avatar
Nicole Cordes committed
340
		$this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
341
342
343
		// Initialize menu
		$this->menuConfig();
		// Setting sys language from session var:
344
		$this->current_sys_language = (int)$this->MOD_SETTINGS['language'];
345
346
		// CSH / Descriptions:
		$this->descrTable = '_MOD_' . $this->MCONF['name'];
347
348
349

		$this->markers['SEARCHBOX'] = '';
		$this->markers['BUTTONLIST_ADDITIONAL'] = '';
350
351
352
353
354
355
356
357
	}

	/**
	 * Initialize menu array
	 *
	 * @return void
	 */
	public function menuConfig() {
358
		$lang = $this->getLanguageService();
359
360
361
362
		// MENU-ITEMS:
		$this->MOD_MENU = array(
			'tt_content_showHidden' => '',
			'function' => array(
363
364
365
				0 => $lang->getLL('m_function_0'),
				1 => $lang->getLL('m_function_1'),
				2 => $lang->getLL('m_function_2')
366
367
			),
			'language' => array(
368
				0 => $lang->getLL('m_default')
369
370
371
372
373
			)
		);
		// example settings:
		// 	$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['cms']['db_layout']['addTables']['tx_myext'] =
		//		array ('default' => array(
374
		//				'MENU' => 'LLL:EXT:tx_myext/locallang_db.xlf:menuDefault',
375
376
377
378
379
380
381
382
383
384
		//				'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) {
385
						$this->MOD_MENU[$table][$key] = $lang->sL($settings['MENU']);
386
387
388
389
390
391
					}
				}
			}
		}
		// 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);
392
393
394
		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'];
395
396
397
			}
		}
		// Find if there are ANY languages at all (and if not, remove the language option from function menu).
398
		$count = $this->getDatabaseConnection()->exec_SELECTcountRows('uid', 'sys_language', $this->getBackendUser()->isAdmin() ? '' : 'hidden=0');
399
400
401
402
		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
403
404
		$this->modSharedTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.SHARED');
		$this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->MCONF['name']);
405
406
407
		if ($this->modTSconfig['properties']['QEisDefault']) {
			ksort($this->MOD_MENU['function']);
		}
Nicole Cordes's avatar
Nicole Cordes committed
408
		$this->MOD_MENU['function'] = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $this->MOD_MENU['function'], 'menu.function');
409
		// Remove QuickEdit as option if page type is not...
410
		if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'] . ',6', $this->pageinfo['doktype'])) {
411
412
413
414
415
416
417
			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
418
		$this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_layout');
419
		// For all elements to be shown in draft workspaces & to also show hidden elements by default if user hasn't disabled the option
420
		if ($this->getBackendUser()->workspace != 0 || $this->MOD_SETTINGS['tt_content_showHidden'] !== '0') {
421
422
423
424
425
426
427
428
429
430
431
			$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) {
432
433
			$tce = GeneralUtility::makeInstance(DataHandler::class);
			$tce->stripslashes_values = FALSE;
434
435
436
437
438
439
440
441
442
443
444
445
			$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 = '';
446
		$lang = $this->getLanguageService();
447
		// If page is a folder
448
		if ($this->pageinfo['doktype'] == PageRepository::DOKTYPE_SYSFOLDER) {
449
			// Access to list module
450
			$moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
451
452
453
			$moduleLoader->load($GLOBALS['TBE_MODULES']);
			$modules = $moduleLoader->modules;
			if (is_array($modules['web']['sub']['list'])) {
454
455
456
				$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>';
457
458
459
460

				$view = GeneralUtility::makeInstance(StandaloneView::class);
				$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
				$view->assignMultiple(array(
461
462
					'title' => $title,
					'message' => $message,
463
464
465
					'state' => InfoboxViewHelper::STATE_INFO
				));
				$content .= $view->render();
466
467
468
469
			}
		}
		// If content from different pid is displayed
		if ($this->pageinfo['content_from_pid']) {
470
			$contentPage = BackendUtility::getRecord('pages', (int)$this->pageinfo['content_from_pid']);
Nicole Cordes's avatar
Nicole Cordes committed
471
			$title = BackendUtility::getRecordTitle('pages', $contentPage);
472
			$linkToPid = $this->local_linkThisScript(array('id' => $this->pageinfo['content_from_pid']));
473
			$link = '<a href="' . $linkToPid . '">' . htmlspecialchars($title) . ' (PID ' . (int)$this->pageinfo['content_from_pid'] . ')</a>';
474
			$flashMessage = GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('content_from_pid_title'), $link), '', FlashMessage::INFO);
475
476
477
478
479
			$content .= $flashMessage->render();
		}
		return $content;
	}

480
481
482
483
484
485
	/**
	 *
	 * @return string $title
	 */
	protected function getLocalizedPageTitle() {
		if ($this->current_sys_language > 0) {
486
			$overlayRecord = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
487
488
				'title',
				'pages_language_overlay',
489
490
				'pid = ' . (int)$this->id .
						' AND sys_language_uid = ' . (int)$this->current_sys_language .
Nicole Cordes's avatar
Nicole Cordes committed
491
492
						BackendUtility::deleteClause('pages_language_overlay') .
						BackendUtility::versioningPlaceholderClause('pages_language_overlay'),
493
494
495
496
497
498
499
500
501
502
503
				'',
				'',
				'',
				'sys_language_uid'
			);
			return $overlayRecord['title'];
		} else {
			return $this->pageinfo['title'];
		}
	}

504
505
506
507
508
509
510
	/**
	 * Main function.
	 * Creates some general objects and calls other functions for the main rendering of module content.
	 *
	 * @return void
	 */
	public function main() {
511
		$lang = $this->getLanguageService();
512
513
514
515
516
		// 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:
517
			$this->CALC_PERMS = $this->getBackendUser()->calcPerms($this->pageinfo);
518
519
			$this->EDIT_CONTENT = $this->pageIsNotLockedForEditors();

520
			// Start document template object:
521
			$this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
522
			$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout.html');
523
524
525
526

			// override the default jumpToUrl
			$this->doc->JScodeArray['jumpToUrl'] = '
				function jumpToUrl(URL,formEl) {
527
					if (document.editform && TBE_EDITOR.isFormChanged)	{	// Check if the function exists... (works in all browsers?)
528
						if (!TBE_EDITOR.isFormChanged()) {
529
530
531
532
							window.location.href = URL;
						} else if (formEl) {
							if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
						}
533
534
535
					} else {
						window.location.href = URL;
					}
536
				}
537
538
539
540
541
';

			$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 . ';
542
			' . ($this->popView ? BackendUtility::viewOnClick($this->id, '', BackendUtility::BEgetRootLine($this->id)) : '') . '
543
544

				function deleteRecord(table,id,url) {	//
545
546
					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";
547
548
549
550
551
					}
					return false;
				}
			');
			$this->doc->JScode .= $this->doc->wrapScriptTags('
552
				var DTM_array = [];
553
				var DTM_origClass = "";
554
555
556

					// if tabs are used in a popup window the array might not exists
				if(!top.DTM_currentTabs) {
557
					top.DTM_currentTabs = [];
558
559
560
561
562
563
564
				}

				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
565
566
								document.getElementById(DTM_array[idBase][cnt]+"-DIV").className = "tab-pane";
								document.getElementById(DTM_array[idBase][cnt]+"-MENU").attributes.getNamedItem("class").value = "tab";
567
568
569
570
571
572
							}
						}
					}

						// Showing one:
					if (document.getElementById(idBase+"-"+index+"-DIV")) {
Benjamin Kott's avatar
Benjamin Kott committed
573
574
						if (doToogle && document.getElementById(idBase+"-"+index+"-DIV").className === "tab-pane active") {
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane";
575
							if(DTM_origClass=="") {
Benjamin Kott's avatar
Benjamin Kott committed
576
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "tab";
577
578
579
580
581
							} else {
								DTM_origClass = "tab";
							}
							top.DTM_currentTabs[idBase] = -1;
						} else {
Benjamin Kott's avatar
Benjamin Kott committed
582
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane active";
583
							if(DTM_origClass=="") {
Benjamin Kott's avatar
Benjamin Kott committed
584
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "active";
585
							} else {
586
								DTM_origClass = "active";
587
588
589
590
591
592
593
594
595
							}
							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
596
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane";
597
							if(isInit) {
Benjamin Kott's avatar
Benjamin Kott committed
598
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "tab";
599
600
601
602
603
							} else {
								DTM_origClass = "tab";
							}
							top.DTM_currentTabs[idBase+"-"+index] = 0;
						} else {
Benjamin Kott's avatar
Benjamin Kott committed
604
							document.getElementById(idBase+"-"+index+"-DIV").className = "tab-pane active";
605
							if(isInit) {
Benjamin Kott's avatar
Benjamin Kott committed
606
								document.getElementById(idBase+"-"+index+"-MENU").attributes.getNamedItem("class").value = "active";
607
							} else {
608
								DTM_origClass = "active";
609
610
611
612
613
614
615
							}
							top.DTM_currentTabs[idBase+"-"+index] = 1;
						}
					}
				}
			');
			// Setting doc-header
616
617
618
619
			$this->doc->form = '<form action="' . htmlspecialchars(
				BackendUtility::getModuleUrl(
					'web_layout', array('id' => $this->id, 'imagemode' =>  $this->imagemode)
				)) . '" method="post">';
620
			// Creating the top function menu:
621
			$this->topFuncMenu = BackendUtility::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function'], '', '');
622
			$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'], '', '') : '';
623
			// Find backend layout / coumns
624
			$backendLayout = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getSelectedBackendLayout', $this->id, $this);
625
			if (!empty($backendLayout['__colPosList'])) {
626
627
628
				$this->colPosList = implode(',', $backendLayout['__colPosList']);
			}
			// Removing duplicates, if any
629
630
			$this->colPosList = array_unique(GeneralUtility::intExplode(',', $this->colPosList));
			// Accessible columns
631
			if (isset($this->modSharedTSconfig['properties']['colPos_list']) && trim($this->modSharedTSconfig['properties']['colPos_list']) !== '') {
632
633
				$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
634
635
				if (!empty($this->colPosList) && !empty($this->activeColPosList)) {
					$this->activeColPosList = array_unique(array_intersect(
636
637
						$this->activeColPosList,
						$this->colPosList
638
					));
639
				}
640
641
			} else {
				$this->activeColPosList = $this->colPosList;
642
			}
643
			$this->activeColPosList = implode(',', $this->activeColPosList);
644
645
			$this->colPosList = implode(',', $this->colPosList);

646
			$body = '';
647
648
649
650
651
652
			$body .= $this->getHeaderFlashMessagesForCurrentPid();
			// Render the primary module content:
			if ($this->MOD_SETTINGS['function'] == 0) {
				// QuickEdit
				$body .= $this->renderQuickEdit();
			} else {
653
654
				// Page title
				$body .= $this->doc->header($this->getLocalizedPageTitle());
655
656
657
658
659
				// All other listings
				$body .= $this->renderListContent();
			}
			// Setting up the buttons and markers for docheader
			$docHeaderButtons = $this->getButtons($this->MOD_SETTINGS['function'] == 0 ? 'quickEdit' : '');
660
661
			$this->markers['CSH'] = $docHeaderButtons['csh'];
			$this->markers['TOP_FUNCTION_MENU'] = $this->topFuncMenu . $this->editSelect;
662
			$this->markers['LANGSELECTOR'] = $languageMenu;
663
			$this->markers['CONTENT'] = $body;
664
			// Build the <body> for the module
665
			$this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $this->markers);
666
			// Renders the module page
667
			$this->content = $this->doc->render($lang->getLL('title'), $this->content);
668
669
		} else {
			// If no access or id value, create empty document:
670
			$this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
671
			$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout.html');
672
			$this->doc->JScode = $this->doc->wrapScriptTags('
673
				if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
674
			');
675
676

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

678
679
			$title = $lang->getLL('clickAPage_header');
			$message = $lang->getLL('clickAPage_content');
680
681
682
683

			$view = GeneralUtility::makeInstance(StandaloneView::class);
			$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
			$view->assignMultiple(array(
684
685
				'title' => $title,
				'message' => $message,
686
687
688
				'state' => InfoboxViewHelper::STATE_INFO
			));
			$body .= $view->render();
689

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
			// 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' => '',
707
708
				'history_record' => '',
				'edit_language' => ''
709
			);
Benni Mack's avatar
Benni Mack committed
710
			$this->markers['CSH'] = '';
711
712
713
714
			$this->markers['TOP_FUNCTION_MENU'] = '';
			$this->markers['LANGSELECTOR'] = '';
			$this->markers['CONTENT'] = $body;
			$this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $this->markers);
715
			// Renders the module page
716
			$this->content = $this->doc->render($lang->getLL('title'), $this->content);
717
718
719
720
721
722
		}
	}

	/**
	 * Rendering the quick-edit view.
	 *
723
	 * @return string
724
725
	 */
	public function renderQuickEdit() {
726
727
728
		$databaseConnection = $this->getDatabaseConnection();
		$beUser = $this->getBackendUser();
		$lang = $this->getLanguageService();
729
		// Alternative template
730
		$this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout_quickedit.html');
731
		// Alternative form tag; Quick Edit submits its content to tce_db.php.
732
		$this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) . '" method="post" enctype="multipart/form-data" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
733
734
735
736
		// 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;
737
		// If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine
738
		if (substr($edit_record, 0, 9) == '_EDIT_COL') {
739
			$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');
740
			$idListA = array();
741
			while ($cRow = $databaseConnection->sql_fetch_assoc($res)) {
742
743
				$idListA[] = $cRow['uid'];
			}
744
745
			$url = BackendUtility::getModuleUrl('record_edit', array(
				'edit[tt_content][' . implode(',', $idListA) . ']' => 'edit',
746
				'returnUrl' => $this->local_linkThisScript(array('edit_record' => ''))
747
			));
748
			HttpUtility::redirect($url);
749
		}
750
751
		// 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) {
752
753
			$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);
754
755
756
757
			if (is_array($sys_log_row)) {
				$edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid'];
			}
		}
758
759
760
761
762
		// Creating the selector box, allowing the user to select which element to edit:
		$opt = array();
		$is_selected = 0;
		$languageOverlayRecord = '';
		if ($this->current_sys_language) {
763
			list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int)$this->current_sys_language);
764
765
766
		}
		if (is_array($languageOverlayRecord)) {
			$inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid'];
767
			$is_selected += (int)$edit_record == $inValue;
768
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editLanguageHeader', TRUE) . ' ]</option>';
769
770
		} else {
			$inValue = 'pages:' . $this->id;
771
			$is_selected += (int)$edit_record == $inValue;
772
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editPageProperties', TRUE) . ' ]</option>';
773
774
		}
		// Selecting all content elements from this language and allowed colPos:
775
776
777
778
779
		$whereClause = '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');
		if (!$this->getBackendUser()->user['admin']) {
			$whereClause .= ' AND editlock = 0';
		}
		$res = $databaseConnection->exec_SELECTquery('*', 'tt_content', $whereClause, '', 'colPos,sorting');
780
		$colPos = NULL;
781
782
783
		$first = 1;
		// Page is the pid if no record to put this after.
		$prev = $this->id;
784
		while ($cRow = $databaseConnection->sql_fetch_assoc($res)) {
Nicole Cordes's avatar
Nicole Cordes committed
785
			BackendUtility::workspaceOL('tt_content', $cRow);
786
787
788
789
790
791
792
			if (is_array($cRow)) {
				if ($first) {
					if (!$edit_record) {
						$edit_record = 'tt_content:' . $cRow['uid'];
					}
					$first = 0;
				}
793
				if (!isset($colPos) || $cRow['colPos'] !== $colPos) {
794
795
					$colPos = $cRow['colPos'];
					$opt[] = '<option value=""></option>';
796
					$opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), TRUE) . ':__</option>';
797
798
				}
				$inValue = 'tt_content:' . $cRow['uid'];
799
				$is_selected += (int)$edit_record == $inValue;
800
				$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>';
801
802
803
804
805
				$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) {
806
807
			$edit_record = 'tt_content:new/' . $prev . '/' . $colPos;
			$inValue = 'tt_content:new/' . $prev . '/' . $colPos;
808
			$is_selected += (int)$edit_record == $inValue;
809
			$opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('newLabel', 1) . ' ]</option>';
810
811
812
813
		}
		// If none is yet selected...
		if (!$is_selected) {
			$opt[] = '<option value=""></option>';
814
			$opt[] = '<option value="' . $edit_record . '"  selected="selected">[ ' . $lang->getLL('newLabel', TRUE) . ' ]</option>';
815
816
817
818
		}
		// Splitting the edit-record cmd value into table/uid:
		$this->eRParts = explode(':', $edit_record);
		// Delete-button flag?
819
		$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);
820
		// If undo-button should be rendered (depends on available items in sys_history)
821
822
823
824
		$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;
825
826
		}
		// 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
827
828
		$R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
		$R_URL_getvars = GeneralUtility::_GET();
829
		unset($R_URL_getvars['popView']);
830
		unset($R_URL_getvars['new_unique_uid']);
831
		$R_URL_getvars['edit_record'] = $edit_record;
Nicole Cordes's avatar
Nicole Cordes committed
832
		$this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars);
833
834
835
836
837
838
839
		// 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:
840
		$retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+' . GeneralUtility::quoteJSvalue(rawurlencode($this->returnUrl)) : '';
841
		// Drawing the edit record selectbox
842
843
844
		$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>';
845
		$content = '';
846
		// Creating editing form:
847
		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)) {
848
849
850
851
			// 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') {
852
				if ($draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $this->eRParts[0], $uidVal, 'uid')) {
853
854
855
856
					$uidVal = $draftRecord['uid'];
				}
			}
			// Initializing transfer-data object:
857
			$trData = GeneralUtility::makeInstance(DataPreprocessor::class);
858
859
			$trData->addRawData = TRUE;
			$trData->defVals[$this->eRParts[0]] = array(
860
861
				'colPos' => (int)$ex_colPos,
				'sys_language_uid' => (int)$this->current_sys_language
862
863
864
865
			);
			$trData->lockRecords = 1;
			// 'new'
			$trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal);
866
			$new_unique_uid = '';
867
868
869
870
			// Getting/Making the record:
			reset($trData->regTableItems_data);
			$rec = current($trData->regTableItems_data);
			if ($uidVal == 'new') {
871
				$new_unique_uid = uniqid('NEW', TRUE);
872
				$rec['uid'] = $new_unique_uid;
873
				$rec['pid'] = (int)$ex_pid ?: $this->id;
874
875
876
877
				$recordAccess = TRUE;
			} else {
				$rec['uid'] = $uidVal;
				// Checking internals access:
878
				$recordAccess = $beUser->recordEditAccessInternals($this->eRParts[0], $uidVal);
879
880
881
			}
			if (!$recordAccess) {
				// If no edit access, print error message:
882
				$content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : ''), 0, 1);
883
884
885
			} elseif (is_array($rec)) {
				// If the record is an array (which it will always be... :-)
				// Create instance of TCEforms, setting defaults:
886
				$tceForms = GeneralUtility::makeInstance(FormEngine::class);
887
888
				// Render form, wrap it:
				$panel = '';
889
890
				$panel .= $tceForms->getMainFields($this->eRParts[0], $rec);
				$panel = $tceForms->wrapTotal($panel, $rec, $this->eRParts[0]);
891
892
893
				// Add hidden fields:
				$theCode = $panel;
				if ($uidVal == 'new') {
894
					$theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />';
895
				}
896
897
898
				$theCode .= '
					<input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />
					<input type="hidden" name="edit_record" value="' . $edit_record . '" />
899
900
901
902
903
904
905
906
					<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)) . '" />
907
					' . FormEngine::getHiddenTokenField('tceAction');
908
				// Add JavaScript as needed around the form:
909
				$theCode = $tceForms->printNeededJSFunctions_top() . $theCode . $tceForms->printNeededJSFunctions();
910
				// Add warning sign if record was "locked":
Nicole Cordes's avatar
Nicole Cordes committed
911
				if ($lockInfo = BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) {
912
913
					/** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
					$flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING);
914
					/** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
915
					$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
916
917
918
					/** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
					$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
					$defaultFlashMessageQueue->enqueue($flashMessage);
919
920
				}
				// Add whole form as a document section:
921
				$content = $this->doc->section('', $theCode);
922
923
924
			}
		} else {
			// If no edit access, print error message:
925
			$content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />', 0, 1);
926
927
928
		}
		// Bottom controls (function menus):
		$q_count = $this->getNumberOfHiddenElements();
929
930
931
932
933
934
935
936
937
938
939
		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);
		}
940

941
		// Select element matrix:
Nicole Cordes's avatar
Nicole Cordes committed
942
		if ($this->eRParts[0] == 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
943
			$posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class);
944
945
946
			$posMap->cur_sys_language = $this->current_sys_language;
			$HTMLcode = '';
			// CSH:
Benni Mack's avatar
Benni Mack committed
947
			$HTMLcode .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', NULL, '|<br />');
948
949
			$HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI);
			$content .= $this->doc->spacer(20);
950
			$content .= $this->doc->section($lang->getLL('CEonThisPage'), $HTMLcode, 0, 1);
951
952
953
954
955
956
957
958
			$content .= $this->doc->spacer(20);
		}
		return $content;
	}

	/**
	 * Rendering all other listings than QuickEdit
	 *
959
	 * @return string
960
961
	 */
	public function renderListContent() {
962
963
964
965
966
		/** @var $dbList \TYPO3\CMS\Backend\View\PageLayoutView */
		$dbList = GeneralUtility::makeInstance(PageLayoutView::class);
		$dbList->thumbs = $this->imagemode;
		$dbList->no_noWrap = 1;
		$dbList->descrTable = $this->descrTable;
Nicole Cordes's avatar
Nicole Cordes committed
967
		$this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
968
969
970
971
972
973
974
975
976
977
978
979
		$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;
980
		}
981
		$dbList->externalTables = $this->externalTables;
982
		// Create menu for selecting a table to jump to (this is, if more than just pages/tt_content elements are found on the page!)
983
984
		// also fills $dbList->activeTables
		$dbList->getTableMenu($this->id);
985
986
987
988
989
990
991
		// 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()):
992
993
994
		foreach ($dbList->activeTables as $table => $value) {
			$h_func_b = '';
			if (!isset($dbList->externalTables[$table])) {
995
				$q_count = $this->getNumberOfHiddenElements();
996

997
998
999
				if ($q_count > 0) {
					$h_func_b =
						'<div class="checkbox">'
1000
						. '<label for="checkTt_content_showHidden">'
1001
1002
						. '<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>)'
1003
						. '</label>'
1004
1005
						. '</div>';
				}
1006
				// Boolean: Display up/down arrows and edit icons for tt_content records
1007
				$dbList->tt_contentConfig['showCommands'] = 1;
1008
				// Boolean: Display info-marks or not
1009
				$dbList->tt_contentConfig['showInfo'] = 1;
1010
1011
1012
				// Setting up the tt_content columns to show:
				if (is_array($GLOBALS['TCA']['tt_content']['columns']['colPos']['config']['items'])) {
					$colList = array();
1013
					$tcaItems = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getColPosListItemsParsed', $this->id, $this);
1014
1015
1016
1017
1018
1019
1020
					foreach ($tcaItems as $temp) {
						$colList[] = $temp[1];
					}
				} else {
					// ... should be impossible that colPos has no array. But this is the fallback should it make any sense:
					$colList = array('1', '0', '2', '3');
				}
1021
				if ($this->colPosList !== '') {
Nicole Cordes's avatar
Nicole Cordes committed
1022
					$colList = array_intersect(GeneralUtility::intExplode(',', $this->colPosList), $colList);
1023
1024
				}
				// The order of the rows: Default is left(1), Normal(0), right(2), margin(3)
1025
1026
1027
1028
				$dbList->tt_contentConfig['cols'] = implode(',', $colList);
				$dbList->tt_contentConfig['activeCols'] = $this->activeColPosList;
				$dbList->tt_contentConfig['showHidden'] = $this->MOD_SETTINGS['tt_content_showHidden'];
				$dbList->tt_contentConfig['sys_language_uid'] = (int)$this->current_sys_language;
1029
1030
				// If the function menu is set to "Language":
				if ($this->MOD_SETTINGS['function'] == 2) {
1031
1032
1033
					$dbList->tt_contentConfig['languageMode'] = 1;
					$dbList->tt_contentConfig['languageCols'] = $this->MOD_MENU['language'];
					$dbList->tt_contentConfig['languageColsPointer'] = $this->current_sys_language;
1034
1035
1036
				}
			} else {
				if (isset($this->MOD_SETTINGS) && isset($this->MOD_MENU)) {
1037
					$h_func = BackendUtility::getFuncMenu($this->id, 'SET[' . $table . ']', $this->MOD_SETTINGS[$table], $this->MOD_MENU[$table], '', '');
1038
1039
1040
1041
1042
				} else {
					$h_func = '';
				}
			}
			// Start the dblist object:
1043
1044
1045
1046
			$dbList->itemsLimitSingleTable = 1000;
			$dbList->start($this->id, $table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit);
			$dbList->counter = $CMcounter;
			$dbList->ext_function = $this->MOD_SETTINGS['function'];
1047
			// Render versioning selector:
1048
			$dbList->HTMLcode .= $this->doc->getVersionSelector($this->id);
1049
			// Generate the list of elements here:
1050
			$dbList->generateList();
1051
			// Adding the list content to the tableOutput variable:
1052
			$tableOutput[$table] = ($h_func ? $h_func . '<br /><span style="width: 1px; height: 4px; display: inline-block;"></span><br />' : '') . $dbList->HTMLcode . ($h_func_b ? '<span style="width: 1px; height: 10px; display:inline-block;"></span><br />' . $h_func_b : '');
1053
			// ... and any accumulated JavaScript goes the same way!
1054
			$tableJSOutput[$table] = $dbList->JScode;
1055
			// Increase global counter:
1056
			$CMcounter += $dbList->counter;
1057
			// Reset variables after operation:
1058
1059
			$dbList->HTMLcode = '';
			$dbList->JScode = '';
1060
1061
1062
1063
1064
			$h_func = '';
		}
		// END: traverse tables
		// For Context Sensitive Menus:
		$this->doc->getContextMenuCode();
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
		// Init the content
		$content = '';
		// Additional header content
		$headerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'];
		if (is_array($headerContentHook)) {
			foreach ($headerContentHook as $hook) {