3eade47fbef2537397e69b90ab1a73decda69abd
[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 }
194
195 /**
196 * Initializing the module
197 *
198 * @return void
199 */
200 public function init() {
201 $backendUser = $this->getBackendUserAuthentication();
202 $this->perms_clause = $backendUser->getPagePermsClause(1);
203 // Get session data
204 $sessionData = $backendUser->getSessionData(__CLASS__);
205 $this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
206 // GPvars:
207 $this->id = (int)GeneralUtility::_GP('id');
208 $this->pointer = GeneralUtility::_GP('pointer');
209 $this->imagemode = GeneralUtility::_GP('imagemode');
210 $this->table = GeneralUtility::_GP('table');
211 $this->search_field = GeneralUtility::_GP('search_field');
212 $this->search_levels = (int)GeneralUtility::_GP('search_levels');
213 $this->showLimit = GeneralUtility::_GP('showLimit');
214 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
215 $this->clear_cache = GeneralUtility::_GP('clear_cache');
216 $this->cmd = GeneralUtility::_GP('cmd');
217 $this->cmd_table = GeneralUtility::_GP('cmd_table');
218 $sessionData['search_field'] = $this->search_field;
219 // Initialize menu
220 $this->menuConfig();
221 // Store session data
222 $backendUser->setAndSaveSessionData(RecordList::class, $sessionData);
223 $this->getPageRenderer()->addInlineLanguageLabelFile('EXT:lang/locallang_mod_web_list.xlf');
224 }
225
226 /**
227 * Initialize function menu array
228 *
229 * @return void
230 */
231 public function menuConfig() {
232 // MENU-ITEMS:
233 $this->MOD_MENU = array(
234 'bigControlPanel' => '',
235 'clipBoard' => '',
236 'localization' => ''
237 );
238 // Loading module configuration:
239 $this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->moduleName);
240 // Clean up settings:
241 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->moduleName);
242 }
243
244 /**
245 * Clears page cache for the current id, $this->id
246 *
247 * @return void
248 */
249 public function clearCache() {
250 if ($this->clear_cache) {
251 $tce = GeneralUtility::makeInstance(DataHandler::class);
252 $tce->stripslashes_values = 0;
253 $tce->start(array(), array());
254 $tce->clear_cacheCmd($this->id);
255 }
256 }
257
258 /**
259 * Main function, starting the rendering of the list.
260 *
261 * @return void
262 */
263 public function main() {
264 $backendUser = $this->getBackendUserAuthentication();
265 $lang = $this->getLanguageService();
266 // Loading current page record and checking access:
267 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
268 $access = is_array($this->pageinfo) ? 1 : 0;
269 // Start document template object:
270 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
271 $this->doc->backPath = $GLOBALS['BACK_PATH'];
272 $this->doc->setModuleTemplate('EXT:recordlist/Resources/Private/Templates/db_list.html');
273 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
274 $calcPerms = $backendUser->calcPerms($this->pageinfo);
275 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
276 PageActions.setPageId(' . (int)$this->id . ');
277 PageActions.setCanEditPage(' . ($calcPerms & Permission::PAGE_EDIT && !empty($this->id) ? 'true' : 'false') . ');
278 PageActions.initializePageTitleRenaming();
279 }');
280 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip');
281 // Apply predefined values for hidden checkboxes
282 // Set predefined value for DisplayBigControlPanel:
283 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') {
284 $this->MOD_SETTINGS['bigControlPanel'] = TRUE;
285 } elseif ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'deactivated') {
286 $this->MOD_SETTINGS['bigControlPanel'] = FALSE;
287 }
288 // Set predefined value for Clipboard:
289 if ($this->modTSconfig['properties']['enableClipBoard'] === 'activated') {
290 $this->MOD_SETTINGS['clipBoard'] = TRUE;
291 } elseif ($this->modTSconfig['properties']['enableClipBoard'] === 'deactivated') {
292 $this->MOD_SETTINGS['clipBoard'] = FALSE;
293 } else {
294 if ($this->MOD_SETTINGS['clipBoard'] === NULL) {
295 $this->MOD_SETTINGS['clipBoard'] = TRUE;
296 }
297 }
298 // Set predefined value for LocalizationView:
299 if ($this->modTSconfig['properties']['enableLocalizationView'] === 'activated') {
300 $this->MOD_SETTINGS['localization'] = TRUE;
301 } elseif ($this->modTSconfig['properties']['enableLocalizationView'] === 'deactivated') {
302 $this->MOD_SETTINGS['localization'] = FALSE;
303 }
304
305 // Initialize the dblist object:
306 /** @var $dblist RecordList\DatabaseRecordList */
307 $dblist = GeneralUtility::makeInstance(RecordList\DatabaseRecordList::class);
308 $dblist->backPath = $GLOBALS['BACK_PATH'];
309 $dblist->script = BackendUtility::getModuleUrl('web_list');
310 $dblist->calcPerms = $calcPerms;
311 $dblist->thumbs = $backendUser->uc['thumbnailsByDefault'];
312 $dblist->returnUrl = $this->returnUrl;
313 $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0;
314 $dblist->localizationView = $this->MOD_SETTINGS['localization'];
315 $dblist->showClipboard = 1;
316 $dblist->disableSingleTableView = $this->modTSconfig['properties']['disableSingleTableView'];
317 $dblist->listOnlyInSingleTableMode = $this->modTSconfig['properties']['listOnlyInSingleTableView'];
318 $dblist->hideTables = $this->modTSconfig['properties']['hideTables'];
319 $dblist->hideTranslations = $this->modTSconfig['properties']['hideTranslations'];
320 $dblist->tableTSconfigOverTCA = $this->modTSconfig['properties']['table.'];
321 $dblist->allowedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['allowedNewTables'], TRUE);
322 $dblist->deniedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['deniedNewTables'], TRUE);
323 $dblist->newWizards = $this->modTSconfig['properties']['newWizards'] ? 1 : 0;
324 $dblist->pageRow = $this->pageinfo;
325 $dblist->counter++;
326 $dblist->MOD_MENU = array('bigControlPanel' => '', 'clipBoard' => '', 'localization' => '');
327 $dblist->modTSconfig = $this->modTSconfig;
328 $clickTitleMode = trim($this->modTSconfig['properties']['clickTitleMode']);
329 $dblist->clickTitleMode = $clickTitleMode === '' ? 'edit' : $clickTitleMode;
330 if (isset($this->modTSconfig['properties']['tableDisplayOrder.'])) {
331 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
332 $dblist->setTableDisplayOrder($typoScriptService->convertTypoScriptArrayToPlainArray($this->modTSconfig['properties']['tableDisplayOrder.']));
333 }
334 // Clipboard is initialized:
335 // Start clipboard
336 $dblist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
337 // Initialize - reads the clipboard content from the user session
338 $dblist->clipObj->initializeClipboard();
339 // Clipboard actions are handled:
340 // CB is the clipboard command array
341 $CB = GeneralUtility::_GET('CB');
342 if ($this->cmd == 'setCB') {
343 // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked.
344 // By merging we get a full array of checked/unchecked elements
345 // This is set to the 'el' array of the CB after being parsed so only the table in question is registered.
346 $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(GeneralUtility::_POST('CBH'), (array)GeneralUtility::_POST('CBC')), $this->cmd_table);
347 }
348 if (!$this->MOD_SETTINGS['clipBoard']) {
349 // If the clipboard is NOT shown, set the pad to 'normal'.
350 $CB['setP'] = 'normal';
351 }
352 // Execute commands.
353 $dblist->clipObj->setCmd($CB);
354 // Clean up pad
355 $dblist->clipObj->cleanCurrent();
356 // Save the clipboard content
357 $dblist->clipObj->endClipboard();
358 // This flag will prevent the clipboard panel in being shown.
359 // It is set, if the clickmenu-layer is active AND the extended view is not enabled.
360 $dblist->dontShowClipControlPanels = ($dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
361 // 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:
362 if ($access || ($this->id === 0 && $this->search_levels > 0 && $this->search_field !== '')) {
363 // Deleting records...:
364 // 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.
365 if ($this->cmd == 'delete') {
366 $items = $dblist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), $this->cmd_table, 1);
367 if (!empty($items)) {
368 $cmd = array();
369 foreach ($items as $iK => $value) {
370 $iKParts = explode('|', $iK);
371 $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1;
372 }
373 $tce = GeneralUtility::makeInstance(DataHandler::class);
374 $tce->stripslashes_values = 0;
375 $tce->start(array(), $cmd);
376 $tce->process_cmdmap();
377 if (isset($cmd['pages'])) {
378 BackendUtility::setUpdateSignal('updatePageTree');
379 }
380 $tce->printLogErrorMessages(GeneralUtility::getIndpEnv('REQUEST_URI'));
381 }
382 }
383 // Initialize the listing object, dblist, for rendering the list:
384 $this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
385 $dblist->start($this->id, $this->table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit);
386 $dblist->setDispFields();
387 // Render versioning selector:
388 if (ExtensionManagementUtility::isLoaded('version')) {
389 $dblist->HTMLcode .= $this->doc->getVersionSelector($this->id);
390 }
391 // Render the list of tables:
392 $dblist->generateList();
393 $listUrl = substr($dblist->listURL(), strlen($GLOBALS['BACK_PATH']));
394 // Add JavaScript functions to the page:
395 $this->doc->JScode = $this->doc->wrapScriptTags('
396 function jumpExt(URL,anchor) { //
397 var anc = anchor?anchor:"";
398 window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
399 return false;
400 }
401 function jumpSelf(URL) { //
402 window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
403 return false;
404 }
405
406 function setHighlight(id) { //
407 top.fsMod.recentIds["web"]=id;
408 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
409
410 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
411 top.content.nav_frame.refresh_nav();
412 }
413 }
414 ' . $this->doc->redirectUrls($listUrl) . '
415 ' . $dblist->CBfunctions() . '
416 function editRecords(table,idList,addParams,CBflag) { //
417 window.location.href="' . BackendUtility::getModuleUrl('record_edit', array('returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'))) . '&edit["+table+"]["+idList+"]=edit"+addParams;
418 }
419 function editList(table,idList) { //
420 var list="";
421
422 // Checking how many is checked, how many is not
423 var pointer=0;
424 var pos = idList.indexOf(",");
425 while (pos!=-1) {
426 if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
427 list+=idList.substr(pointer,pos-pointer)+",";
428 }
429 pointer=pos+1;
430 pos = idList.indexOf(",",pointer);
431 }
432 if (cbValue(table+"|"+idList.substr(pointer))) {
433 list+=idList.substr(pointer)+",";
434 }
435
436 return list ? list : idList;
437 }
438
439 if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
440 ');
441 // Setting up the context sensitive menu:
442 $this->doc->getContextMenuCode();
443 }
444 // access
445 // Begin to compile the whole page, starting out with page header:
446 if (!$this->id) {
447 $this->body = $this->doc->header($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']);
448 } else {
449 $this->body = $this->doc->header($this->pageinfo['title']);
450 }
451
452 if (!empty($dblist->HTMLcode)) {
453 $output = $dblist->HTMLcode;
454 } else {
455 $output = $flashMessage = GeneralUtility::makeInstance(
456 FlashMessage::class,
457 $lang->getLL('noRecordsOnThisPage'),
458 '',
459 FlashMessage::INFO
460 )->render();
461 }
462
463 $this->body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">';
464 $this->body .= $output;
465 $this->body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
466 // If a listing was produced, create the page footer with search form etc:
467 if ($dblist->HTMLcode) {
468 // Making field select box (when extended view for a single table is enabled):
469 if ($dblist->table) {
470 $this->body .= $dblist->fieldSelectBox($dblist->table);
471 }
472 // Adding checkbox options for extended listing and clipboard display:
473 $this->body .= '
474
475 <!--
476 Listing options for extended view, clipboard and localization view
477 -->
478 <div class="typo3-listOptions">
479 <form action="" method="post">';
480
481 // Add "display bigControlPanel" checkbox:
482 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'selectable') {
483 $this->body .= '<div class="checkbox">' .
484 '<label for="checkLargeControl">' .
485 BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $this->MOD_SETTINGS['bigControlPanel'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLargeControl"') .
486 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('largeControl', TRUE)) .
487 '</label>' .
488 '</div>';
489 }
490
491 // Add "clipboard" checkbox:
492 if ($this->modTSconfig['properties']['enableClipBoard'] === 'selectable') {
493 if ($dblist->showClipboard) {
494 $this->body .= '<div class="checkbox">' .
495 '<label for="checkShowClipBoard">' .
496 BackendUtility::getFuncCheck($this->id, 'SET[clipBoard]', $this->MOD_SETTINGS['clipBoard'], '', $this->table ? '&table=' . $this->table : '', 'id="checkShowClipBoard"') .
497 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('showClipBoard', TRUE)) .
498 '</label>' .
499 '</div>';
500 }
501 }
502
503 // Add "localization view" checkbox:
504 if ($this->modTSconfig['properties']['enableLocalizationView'] === 'selectable') {
505 $this->body .= '<div class="checkbox">' .
506 '<label for="checkLocalization">' .
507 BackendUtility::getFuncCheck($this->id, 'SET[localization]', $this->MOD_SETTINGS['localization'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLocalization"') .
508 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $lang->getLL('localization', TRUE)) .
509 '</label>' .
510 '</div>';
511 }
512
513 $this->body .= '
514 </form>
515 </div>';
516 }
517 // Printing clipboard if enabled
518 if ($this->MOD_SETTINGS['clipBoard'] && $dblist->showClipboard && ($dblist->HTMLcode || $dblist->clipObj->hasElements())) {
519 $this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>';
520 }
521 // Additional footer content
522 $footerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'];
523 if (is_array($footerContentHook)) {
524 foreach ($footerContentHook as $hook) {
525 $params = array();
526 $this->body .= GeneralUtility::callUserFunction($hook, $params, $this);
527 }
528 }
529 // Setting up the buttons and markers for docheader
530 $docHeaderButtons = $dblist->getButtons();
531 $markers = array(
532 'CSH' => $docHeaderButtons['csh'],
533 'CONTENT' => $this->body,
534 'EXTRACONTAINERCLASS' => $this->table ? 'singletable' : '',
535 'BUTTONLIST_ADDITIONAL' => '',
536 'SEARCHBOX' => '',
537 );
538 // searchbox toolbar
539 if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dblist->HTMLcode || !empty($dblist->searchString))) {
540 $markers['SEARCHBOX'] = $dblist->getSearchBox();
541 $markers['BUTTONLIST_ADDITIONAL'] = '<a href="#" onclick="toggleSearchToolbox(); return false;" title="'
542 . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.title.searchIcon', TRUE) . '">'
543 . IconUtility::getSpriteIcon('apps-toolbar-menu-search').'</a>';
544 }
545 // Build the <body> for the module
546 $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
547 // Renders the module page
548 $this->content = $this->doc->render('DB list', $this->content);
549 }
550
551 /**
552 * Outputting the accumulated content to screen
553 *
554 * @return void
555 */
556 public function printContent() {
557 echo $this->content;
558 }
559
560 /**
561 * @return BackendUserAuthentication
562 */
563 protected function getBackendUserAuthentication() {
564 return $GLOBALS['BE_USER'];
565 }
566
567 /**
568 * @return LanguageService
569 */
570 protected function getLanguageService() {
571 return $GLOBALS['LANG'];
572 }
573
574 /**
575 * @return PageRenderer
576 */
577 protected function getPageRenderer() {
578 if ($this->pageRenderer === NULL) {
579 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
580 }
581
582 return $this->pageRenderer;
583 }
584
585 }