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