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