[TASK] Prevent remaining DocumentTemplate->getPageRenderer() calls
[Packages/TYPO3.CMS.git] / typo3 / sysext / recordlist / Classes / RecordList.php
1 <?php
2 namespace TYPO3\CMS\Recordlist;
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
17 use TYPO3\CMS\Backend\Clipboard\Clipboard;
18 use TYPO3\CMS\Backend\Template\DocumentTemplate;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Backend\Utility\IconUtility;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\DataHandling\DataHandler;
23 use TYPO3\CMS\Core\Messaging\FlashMessage;
24 use TYPO3\CMS\Core\Page\PageRenderer;
25 use TYPO3\CMS\Core\Type\Bitmask\Permission;
26 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28 use TYPO3\CMS\Core\Utility\MathUtility;
29 use TYPO3\CMS\Extbase\Service\TypoScriptService;
30 use TYPO3\CMS\Lang\LanguageService;
31
32 /**
33 * Script Class for the Web > List module; rendering the listing of records on a page
34 */
35 class RecordList {
36
37 /**
38 * Page Id for which to make the listing
39 *
40 * @var int
41 */
42 public $id;
43
44 /**
45 * Pointer - for browsing list of records.
46 *
47 * @var int
48 */
49 public $pointer;
50
51 /**
52 * Thumbnails or not
53 *
54 * @var string
55 */
56 public $imagemode;
57
58 /**
59 * Which table to make extended listing for
60 *
61 * @var string
62 */
63 public $table;
64
65 /**
66 * Search-fields
67 *
68 * @var string
69 */
70 public $search_field;
71
72 /**
73 * Search-levels
74 *
75 * @var int
76 */
77 public $search_levels;
78
79 /**
80 * Show-limit
81 *
82 * @var int
83 */
84 public $showLimit;
85
86 /**
87 * Return URL
88 *
89 * @var string
90 */
91 public $returnUrl;
92
93 /**
94 * Clear-cache flag - if set, clears page cache for current id.
95 *
96 * @var bool
97 */
98 public $clear_cache;
99
100 /**
101 * Command: Eg. "delete" or "setCB" (for TCEmain / clipboard operations)
102 *
103 * @var string
104 */
105 public $cmd;
106
107 /**
108 * Table on which the cmd-action is performed.
109 *
110 * @var string
111 */
112 public $cmd_table;
113
114 /**
115 * Page select perms clause
116 *
117 * @var int
118 */
119 public $perms_clause;
120
121 /**
122 * Module TSconfig
123 *
124 * @var array
125 */
126 public $modTSconfig;
127
128 /**
129 * Current ids page record
130 *
131 * @var mixed[]|bool
132 */
133 public $pageinfo;
134
135 /**
136 * Document template object
137 *
138 * @var DocumentTemplate
139 */
140 public $doc;
141
142 /**
143 * Module configuration
144 *
145 * @var array
146 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8.
147 */
148 public $MCONF = array();
149
150 /**
151 * Menu configuration
152 *
153 * @var string[]
154 */
155 public $MOD_MENU = array();
156
157 /**
158 * Module settings (session variable)
159 *
160 * @var string[]
161 */
162 public $MOD_SETTINGS = array();
163
164 /**
165 * Module output accumulation
166 *
167 * @var string
168 */
169 public $content;
170
171 /**
172 * The name of the module
173 *
174 * @var string
175 */
176 protected $moduleName = 'web_list';
177
178 /**
179 * @var string
180 */
181 public $body = '';
182
183 /**
184 * @var PageRenderer
185 */
186 protected $pageRenderer = NULL;
187
188 /**
189 * Constructor
190 */
191 public function __construct() {
192 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_mod_web_list.xlf');
193 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
194 $this->pageRenderer->loadJquery();
195 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
196 }
197
198 /**
199 * Initializing the module
200 *
201 * @return void
202 */
203 public function init() {
204 $backendUser = $this->getBackendUserAuthentication();
205 $this->perms_clause = $backendUser->getPagePermsClause(1);
206 // Get session data
207 $sessionData = $backendUser->getSessionData(__CLASS__);
208 $this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
209 // GPvars:
210 $this->id = (int)GeneralUtility::_GP('id');
211 $this->pointer = GeneralUtility::_GP('pointer');
212 $this->imagemode = GeneralUtility::_GP('imagemode');
213 $this->table = GeneralUtility::_GP('table');
214 $this->search_field = GeneralUtility::_GP('search_field');
215 $this->search_levels = (int)GeneralUtility::_GP('search_levels');
216 $this->showLimit = GeneralUtility::_GP('showLimit');
217 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
218 $this->clear_cache = GeneralUtility::_GP('clear_cache');
219 $this->cmd = GeneralUtility::_GP('cmd');
220 $this->cmd_table = GeneralUtility::_GP('cmd_table');
221 $sessionData['search_field'] = $this->search_field;
222 // Initialize menu
223 $this->menuConfig();
224 // Store session data
225 $backendUser->setAndSaveSessionData(RecordList::class, $sessionData);
226 $this->getPageRenderer()->addInlineLanguageLabelFile('EXT:lang/locallang_mod_web_list.xlf');
227 }
228
229 /**
230 * Initialize function menu array
231 *
232 * @return void
233 */
234 public function menuConfig() {
235 // MENU-ITEMS:
236 $this->MOD_MENU = array(
237 'bigControlPanel' => '',
238 'clipBoard' => '',
239 'localization' => ''
240 );
241 // Loading module configuration:
242 $this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->moduleName);
243 // Clean up settings:
244 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->moduleName);
245 }
246
247 /**
248 * Clears page cache for the current id, $this->id
249 *
250 * @return void
251 */
252 public function clearCache() {
253 if ($this->clear_cache) {
254 $tce = GeneralUtility::makeInstance(DataHandler::class);
255 $tce->stripslashes_values = 0;
256 $tce->start(array(), array());
257 $tce->clear_cacheCmd($this->id);
258 }
259 }
260
261 /**
262 * Main function, starting the rendering of the list.
263 *
264 * @return void
265 */
266 public function main() {
267 $backendUser = $this->getBackendUserAuthentication();
268 $lang = $this->getLanguageService();
269 // Loading current page record and checking access:
270 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
271 $access = is_array($this->pageinfo) ? 1 : 0;
272 // Start document template object:
273 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
274 $this->doc->setModuleTemplate('EXT:recordlist/Resources/Private/Templates/db_list.html');
275 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
276 $calcPerms = $backendUser->calcPerms($this->pageinfo);
277 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
278 PageActions.setPageId(' . (int)$this->id . ');
279 PageActions.setCanEditPage(' . ($calcPerms & Permission::PAGE_EDIT && !empty($this->id) ? 'true' : 'false') . ');
280 PageActions.initializePageTitleRenaming();
281 }');
282 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip');
283 // Apply predefined values for hidden checkboxes
284 // Set predefined value for DisplayBigControlPanel:
285 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') {
286 $this->MOD_SETTINGS['bigControlPanel'] = TRUE;
287 } elseif ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'deactivated') {
288 $this->MOD_SETTINGS['bigControlPanel'] = FALSE;
289 }
290 // Set predefined value for Clipboard:
291 if ($this->modTSconfig['properties']['enableClipBoard'] === 'activated') {
292 $this->MOD_SETTINGS['clipBoard'] = TRUE;
293 } elseif ($this->modTSconfig['properties']['enableClipBoard'] === 'deactivated') {
294 $this->MOD_SETTINGS['clipBoard'] = FALSE;
295 } else {
296 if ($this->MOD_SETTINGS['clipBoard'] === NULL) {
297 $this->MOD_SETTINGS['clipBoard'] = TRUE;
298 }
299 }
300 // Set predefined value for LocalizationView:
301 if ($this->modTSconfig['properties']['enableLocalizationView'] === 'activated') {
302 $this->MOD_SETTINGS['localization'] = TRUE;
303 } elseif ($this->modTSconfig['properties']['enableLocalizationView'] === 'deactivated') {
304 $this->MOD_SETTINGS['localization'] = FALSE;
305 }
306
307 // Initialize the dblist object:
308 /** @var $dblist RecordList\DatabaseRecordList */
309 $dblist = GeneralUtility::makeInstance(RecordList\DatabaseRecordList::class);
310 $dblist->script = BackendUtility::getModuleUrl('web_list');
311 $dblist->calcPerms = $calcPerms;
312 $dblist->thumbs = $backendUser->uc['thumbnailsByDefault'];
313 $dblist->returnUrl = $this->returnUrl;
314 $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0;
315 $dblist->localizationView = $this->MOD_SETTINGS['localization'];
316 $dblist->showClipboard = 1;
317 $dblist->disableSingleTableView = $this->modTSconfig['properties']['disableSingleTableView'];
318 $dblist->listOnlyInSingleTableMode = $this->modTSconfig['properties']['listOnlyInSingleTableView'];
319 $dblist->hideTables = $this->modTSconfig['properties']['hideTables'];
320 $dblist->hideTranslations = $this->modTSconfig['properties']['hideTranslations'];
321 $dblist->tableTSconfigOverTCA = $this->modTSconfig['properties']['table.'];
322 $dblist->allowedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['allowedNewTables'], TRUE);
323 $dblist->deniedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['deniedNewTables'], TRUE);
324 $dblist->newWizards = $this->modTSconfig['properties']['newWizards'] ? 1 : 0;
325 $dblist->pageRow = $this->pageinfo;
326 $dblist->counter++;
327 $dblist->MOD_MENU = array('bigControlPanel' => '', 'clipBoard' => '', 'localization' => '');
328 $dblist->modTSconfig = $this->modTSconfig;
329 $clickTitleMode = trim($this->modTSconfig['properties']['clickTitleMode']);
330 $dblist->clickTitleMode = $clickTitleMode === '' ? 'edit' : $clickTitleMode;
331 if (isset($this->modTSconfig['properties']['tableDisplayOrder.'])) {
332 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
333 $dblist->setTableDisplayOrder($typoScriptService->convertTypoScriptArrayToPlainArray($this->modTSconfig['properties']['tableDisplayOrder.']));
334 }
335 // Clipboard is initialized:
336 // Start clipboard
337 $dblist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
338 // Initialize - reads the clipboard content from the user session
339 $dblist->clipObj->initializeClipboard();
340 // Clipboard actions are handled:
341 // CB is the clipboard command array
342 $CB = GeneralUtility::_GET('CB');
343 if ($this->cmd == 'setCB') {
344 // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked.
345 // By merging we get a full array of checked/unchecked elements
346 // This is set to the 'el' array of the CB after being parsed so only the table in question is registered.
347 $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(GeneralUtility::_POST('CBH'), (array)GeneralUtility::_POST('CBC')), $this->cmd_table);
348 }
349 if (!$this->MOD_SETTINGS['clipBoard']) {
350 // If the clipboard is NOT shown, set the pad to 'normal'.
351 $CB['setP'] = 'normal';
352 }
353 // Execute commands.
354 $dblist->clipObj->setCmd($CB);
355 // Clean up pad
356 $dblist->clipObj->cleanCurrent();
357 // Save the clipboard content
358 $dblist->clipObj->endClipboard();
359 // This flag will prevent the clipboard panel in being shown.
360 // It is set, if the clickmenu-layer is active AND the extended view is not enabled.
361 $dblist->dontShowClipControlPanels = ($dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
362 // If there is access to the page or root page is used for searching, then render the list contents and set up the document template object:
363 if ($access || ($this->id === 0 && $this->search_levels > 0 && $this->search_field !== '')) {
364 // Deleting records...:
365 // Has not to do with the clipboard but is simply the delete action. The clipboard object is used to clean up the submitted entries to only the selected table.
366 if ($this->cmd == 'delete') {
367 $items = $dblist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), $this->cmd_table, 1);
368 if (!empty($items)) {
369 $cmd = array();
370 foreach ($items as $iK => $value) {
371 $iKParts = explode('|', $iK);
372 $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1;
373 }
374 $tce = GeneralUtility::makeInstance(DataHandler::class);
375 $tce->stripslashes_values = 0;
376 $tce->start(array(), $cmd);
377 $tce->process_cmdmap();
378 if (isset($cmd['pages'])) {
379 BackendUtility::setUpdateSignal('updatePageTree');
380 }
381 $tce->printLogErrorMessages(GeneralUtility::getIndpEnv('REQUEST_URI'));
382 }
383 }
384 // Initialize the listing object, dblist, for rendering the list:
385 $this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
386 $dblist->start($this->id, $this->table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit);
387 $dblist->setDispFields();
388 // Render versioning selector:
389 if (ExtensionManagementUtility::isLoaded('version')) {
390 $dblist->HTMLcode .= $this->doc->getVersionSelector($this->id);
391 }
392 // Render the list of tables:
393 $dblist->generateList();
394 $listUrl = $dblist->listURL();
395 // Add JavaScript functions to the page:
396 $this->doc->JScode = $this->doc->wrapScriptTags('
397 function jumpExt(URL,anchor) { //
398 var anc = anchor?anchor:"";
399 window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
400 return false;
401 }
402 function jumpSelf(URL) { //
403 window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
404 return false;
405 }
406
407 function setHighlight(id) { //
408 top.fsMod.recentIds["web"]=id;
409 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
410
411 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
412 top.content.nav_frame.refresh_nav();
413 }
414 }
415 ' . $this->doc->redirectUrls($listUrl) . '
416 ' . $dblist->CBfunctions() . '
417 function editRecords(table,idList,addParams,CBflag) { //
418 window.location.href="' . BackendUtility::getModuleUrl('record_edit', array('returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'))) . '&edit["+table+"]["+idList+"]=edit"+addParams;
419 }
420 function editList(table,idList) { //
421 var list="";
422
423 // Checking how many is checked, how many is not
424 var pointer=0;
425 var pos = idList.indexOf(",");
426 while (pos!=-1) {
427 if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
428 list+=idList.substr(pointer,pos-pointer)+",";
429 }
430 pointer=pos+1;
431 pos = idList.indexOf(",",pointer);
432 }
433 if (cbValue(table+"|"+idList.substr(pointer))) {
434 list+=idList.substr(pointer)+",";
435 }
436
437 return list ? list : idList;
438 }
439
440 if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
441 ');
442 // Setting up the context sensitive menu:
443 $this->doc->getContextMenuCode();
444 }
445 // access
446 // Begin to compile the whole page, starting out with page header:
447 if (!$this->id) {
448 $this->body = $this->doc->header($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']);
449 } else {
450 $this->body = $this->doc->header($this->pageinfo['title']);
451 }
452
453 if (!empty($dblist->HTMLcode)) {
454 $output = $dblist->HTMLcode;
455 } else {
456 $output = $flashMessage = GeneralUtility::makeInstance(
457 FlashMessage::class,
458 $lang->getLL('noRecordsOnThisPage'),
459 '',
460 FlashMessage::INFO
461 )->render();
462 }
463
464 $this->body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">';
465 $this->body .= $output;
466 $this->body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
467 // If a listing was produced, create the page footer with search form etc:
468 if ($dblist->HTMLcode) {
469 // Making field select box (when extended view for a single table is enabled):
470 if ($dblist->table) {
471 $this->body .= $dblist->fieldSelectBox($dblist->table);
472 }
473 // Adding checkbox options for extended listing and clipboard display:
474 $this->body .= '
475
476 <!--
477 Listing options for extended view, clipboard and localization view
478 -->
479 <div class="typo3-listOptions">
480 <form action="" method="post">';
481
482 // Add "display bigControlPanel" checkbox:
483 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'selectable') {
484 $this->body .= '<div class="checkbox">' .
485 '<label for="checkLargeControl">' .
486 BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $this->MOD_SETTINGS['bigControlPanel'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLargeControl"') .
487 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('largeControl', TRUE)) .
488 '</label>' .
489 '</div>';
490 }
491
492 // Add "clipboard" checkbox:
493 if ($this->modTSconfig['properties']['enableClipBoard'] === 'selectable') {
494 if ($dblist->showClipboard) {
495 $this->body .= '<div class="checkbox">' .
496 '<label for="checkShowClipBoard">' .
497 BackendUtility::getFuncCheck($this->id, 'SET[clipBoard]', $this->MOD_SETTINGS['clipBoard'], '', $this->table ? '&table=' . $this->table : '', 'id="checkShowClipBoard"') .
498 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('showClipBoard', TRUE)) .
499 '</label>' .
500 '</div>';
501 }
502 }
503
504 // Add "localization view" checkbox:
505 if ($this->modTSconfig['properties']['enableLocalizationView'] === 'selectable') {
506 $this->body .= '<div class="checkbox">' .
507 '<label for="checkLocalization">' .
508 BackendUtility::getFuncCheck($this->id, 'SET[localization]', $this->MOD_SETTINGS['localization'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLocalization"') .
509 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('localization', TRUE)) .
510 '</label>' .
511 '</div>';
512 }
513
514 $this->body .= '
515 </form>
516 </div>';
517 }
518 // Printing clipboard if enabled
519 if ($this->MOD_SETTINGS['clipBoard'] && $dblist->showClipboard && ($dblist->HTMLcode || $dblist->clipObj->hasElements())) {
520 $this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>';
521 }
522 // Additional footer content
523 $footerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'];
524 if (is_array($footerContentHook)) {
525 foreach ($footerContentHook as $hook) {
526 $params = array();
527 $this->body .= GeneralUtility::callUserFunction($hook, $params, $this);
528 }
529 }
530 // Setting up the buttons and markers for docheader
531 $docHeaderButtons = $dblist->getButtons();
532 $markers = array(
533 'CSH' => $docHeaderButtons['csh'],
534 'CONTENT' => $this->body,
535 'EXTRACONTAINERCLASS' => $this->table ? 'singletable' : '',
536 'BUTTONLIST_ADDITIONAL' => '',
537 'SEARCHBOX' => '',
538 );
539 // searchbox toolbar
540 if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dblist->HTMLcode || !empty($dblist->searchString))) {
541 $markers['SEARCHBOX'] = $dblist->getSearchBox();
542 $markers['BUTTONLIST_ADDITIONAL'] = '<a href="#" onclick="toggleSearchToolbox(); return false;" title="'
543 . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.title.searchIcon', TRUE) . '">'
544 . IconUtility::getSpriteIcon('apps-toolbar-menu-search').'</a>';
545 }
546 // Build the <body> for the module
547 $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
548 // Renders the module page
549 $this->content = $this->doc->render('DB list', $this->content);
550 }
551
552 /**
553 * Outputting the accumulated content to screen
554 *
555 * @return void
556 */
557 public function printContent() {
558 echo $this->content;
559 }
560
561 /**
562 * @return BackendUserAuthentication
563 */
564 protected function getBackendUserAuthentication() {
565 return $GLOBALS['BE_USER'];
566 }
567
568 /**
569 * @return LanguageService
570 */
571 protected function getLanguageService() {
572 return $GLOBALS['LANG'];
573 }
574
575 /**
576 * @return PageRenderer
577 */
578 protected function getPageRenderer() {
579 if ($this->pageRenderer === NULL) {
580 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
581 }
582
583 return $this->pageRenderer;
584 }
585
586 }