[TASK] Deprecate PageRenderer->loadJQuery()
[Packages/TYPO3.CMS.git] / typo3 / sysext / recordlist / Classes / Controller / RecordListController.php
1 <?php
2 namespace TYPO3\CMS\Recordlist\Controller;
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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Clipboard\Clipboard;
20 use TYPO3\CMS\Backend\Routing\UriBuilder;
21 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
22 use TYPO3\CMS\Backend\Template\DocumentTemplate;
23 use TYPO3\CMS\Backend\Template\ModuleTemplate;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
26 use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
27 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
28 use TYPO3\CMS\Core\Database\ConnectionPool;
29 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
30 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
31 use TYPO3\CMS\Core\DataHandling\DataHandler;
32 use TYPO3\CMS\Core\Http\HtmlResponse;
33 use TYPO3\CMS\Core\Imaging\Icon;
34 use TYPO3\CMS\Core\Imaging\IconFactory;
35 use TYPO3\CMS\Core\Localization\LanguageService;
36 use TYPO3\CMS\Core\Messaging\FlashMessage;
37 use TYPO3\CMS\Core\Messaging\FlashMessageService;
38 use TYPO3\CMS\Core\Page\PageRenderer;
39 use TYPO3\CMS\Core\Site\Entity\SiteInterface;
40 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
41 use TYPO3\CMS\Core\Type\Bitmask\Permission;
42 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
43 use TYPO3\CMS\Core\Utility\GeneralUtility;
44 use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;
45
46 /**
47 * Script Class for the Web > List module; rendering the listing of records on a page
48 */
49 class RecordListController
50 {
51 use PublicPropertyDeprecationTrait;
52 use PublicMethodDeprecationTrait;
53
54 /**
55 * @var array
56 */
57 private $deprecatedPublicProperties = [
58 'id' => 'Using RecordListController::$id is deprecated and will not be possible anymore in TYPO3 v10.',
59 'pointer' => 'Using RecordListController::$pointer is deprecated and will not be possible anymore in TYPO3 v10.',
60 'table' => 'Using RecordListController::$table is deprecated and will not be possible anymore in TYPO3 v10.',
61 'search_field' => 'Using RecordListController::$search_field is deprecated and will not be possible anymore in TYPO3 v10.',
62 'search_levels' => 'Using RecordListController::$search_levels is deprecated and will not be possible anymore in TYPO3 v10.',
63 'showLimit' => 'Using RecordListController::$showLimit is deprecated and will not be possible anymore in TYPO3 v10.',
64 'returnUrl' => 'Using RecordListController::$returnUrl is deprecated and will not be possible anymore in TYPO3 v10.',
65 'clear_cache' => 'Using RecordListController::$clear_cache is deprecated and will not be possible anymore in TYPO3 v10.',
66 'cmd' => 'Using RecordListController::$cmd is deprecated and will not be possible anymore in TYPO3 v10.',
67 'cmd_table' => 'Using RecordListController::$cmd_table is deprecated and will not be possible anymore in TYPO3 v10.',
68 'perms_clause' => 'Using RecordListController::$perms_clause is deprecated and will not be possible anymore in TYPO3 v10.',
69 'pageinfo' => 'Using RecordListController::$pageinfo is deprecated and will not be possible anymore in TYPO3 v10.',
70 'MOD_MENU' => 'Using RecordListController::$MOD_MENU is deprecated and will not be possible anymore in TYPO3 v10.',
71 'content' => 'Using RecordListController::$content is deprecated and will not be possible anymore in TYPO3 v10.',
72 'body' => 'Using RecordListController::$body is deprecated and will not be possible anymore in TYPO3 v10.',
73 'imagemode' => 'Using RecordListController::$imagemode is deprecated, property will be removed in TYPO3 v10.',
74 'doc' => 'Using RecordListController::$doc is deprecated, property will be removed in TYPO3 v10.',
75 ];
76
77 /**
78 * @var array
79 */
80 private $deprecatedPublicMethods = [
81 'init' => 'Using RecordListController::init() is deprecated and will not be possible anymore in TYPO3 v10.',
82 'menuConfig' => 'Using RecordListController::menuConfig() is deprecated and will not be possible anymore in TYPO3 v10.',
83 'clearCache' => 'Using RecordListController::clearCache() is deprecated and will not be possible anymore in TYPO3 v10.',
84 'main' => 'Using RecordListController::main() is deprecated and will not be possible anymore in TYPO3 v10.',
85 'getModuleTemplate' => 'Using RecordListController::getModuleTemplate() is deprecated and will not be possible anymore in TYPO3 v10.',
86 ];
87
88 /**
89 * Page Id for which to make the listing
90 *
91 * @var int
92 */
93 protected $id;
94
95 /**
96 * Pointer - for browsing list of records.
97 *
98 * @var int
99 */
100 protected $pointer;
101
102 /**
103 * Thumbnails or not
104 *
105 * @var string
106 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
107 */
108 protected $imagemode;
109
110 /**
111 * Which table to make extended listing for
112 *
113 * @var string
114 */
115 protected $table;
116
117 /**
118 * Search-fields
119 *
120 * @var string
121 */
122 protected $search_field;
123
124 /**
125 * Search-levels
126 *
127 * @var int
128 */
129 protected $search_levels;
130
131 /**
132 * Show-limit
133 *
134 * @var int
135 */
136 protected $showLimit;
137
138 /**
139 * Return URL
140 *
141 * @var string
142 */
143 protected $returnUrl;
144
145 /**
146 * Clear-cache flag - if set, clears page cache for current id.
147 *
148 * @var bool
149 */
150 protected $clear_cache;
151
152 /**
153 * Command: Eg. "delete" or "setCB" (for DataHandler / clipboard operations)
154 *
155 * @var string
156 */
157 protected $cmd;
158
159 /**
160 * Table on which the cmd-action is performed.
161 *
162 * @var string
163 */
164 protected $cmd_table;
165
166 /**
167 * Page select perms clause
168 *
169 * @var int
170 */
171 protected $perms_clause;
172
173 /**
174 * Module TSconfig
175 *
176 * @var array
177 * @internal Still used by DatabaseRecordList via $GLOBALS['SOBE']
178 */
179 public $modTSconfig;
180
181 /**
182 * Current ids page record
183 *
184 * @var mixed[]|bool
185 */
186 protected $pageinfo;
187
188 /**
189 * Document template object
190 *
191 * @var DocumentTemplate
192 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
193 */
194 protected $doc;
195
196 /**
197 * Menu configuration
198 *
199 * @var string[]
200 */
201 protected $MOD_MENU = [];
202
203 /**
204 * Module settings (session variable)
205 *
206 * @var string[]
207 * @internal Still used by DatabaseRecordList via $GLOBALS['SOBE']
208 */
209 public $MOD_SETTINGS = [];
210
211 /**
212 * Module output accumulation
213 *
214 * @var string
215 */
216 protected $content;
217
218 /**
219 * @var string
220 */
221 protected $body = '';
222
223 /**
224 * @var PageRenderer
225 */
226 protected $pageRenderer;
227
228 /**
229 * @var IconFactory
230 */
231 protected $iconFactory;
232
233 /**
234 * ModuleTemplate object
235 *
236 * @var ModuleTemplate
237 */
238 protected $moduleTemplate;
239
240 /**
241 * @var SiteInterface
242 */
243 protected $site;
244
245 /**
246 * @var SiteLanguage[]
247 */
248 protected $siteLanguages = [];
249
250 /**
251 * Constructor
252 */
253 public function __construct()
254 {
255 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
256 $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
257 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
258 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Recordlist');
259 }
260
261 /**
262 * Initializing the module
263 */
264 protected function init()
265 {
266 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
267 $backendUser = $this->getBackendUserAuthentication();
268 $this->perms_clause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW);
269 // Get session data
270 $sessionData = $backendUser->getSessionData(__CLASS__);
271 $this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
272 // GPvars:
273 $this->id = (int)GeneralUtility::_GP('id');
274 $this->pointer = GeneralUtility::_GP('pointer');
275 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
276 $this->imagemode = GeneralUtility::_GP('imagemode');
277 $this->table = GeneralUtility::_GP('table');
278 $this->search_field = GeneralUtility::_GP('search_field');
279 $this->search_levels = (int)GeneralUtility::_GP('search_levels');
280 $this->showLimit = GeneralUtility::_GP('showLimit');
281 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
282 $this->clear_cache = GeneralUtility::_GP('clear_cache');
283 $this->cmd = GeneralUtility::_GP('cmd');
284 $this->cmd_table = GeneralUtility::_GP('cmd_table');
285 $sessionData['search_field'] = $this->search_field;
286 // Initialize menu
287 $this->menuConfig();
288 // Store session data
289 $backendUser->setAndSaveSessionData(self::class, $sessionData);
290 $this->getPageRenderer()->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
291 }
292
293 /**
294 * Initialize function menu array
295 */
296 protected function menuConfig()
297 {
298 // MENU-ITEMS:
299 $this->MOD_MENU = [
300 'bigControlPanel' => '',
301 'clipBoard' => '',
302 ];
303 // Loading module configuration:
304 $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.']['web_list.'] ?? [];
305 // Clean up settings:
306 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_list');
307 }
308
309 /**
310 * Clears page cache for the current id, $this->id
311 */
312 protected function clearCache()
313 {
314 if ($this->clear_cache) {
315 $tce = GeneralUtility::makeInstance(DataHandler::class);
316 $tce->start([], []);
317 $tce->clear_cacheCmd($this->id);
318 }
319 }
320
321 /**
322 * Main function, starting the rendering of the list.
323 *
324 * @param ServerRequestInterface $request
325 */
326 protected function main(ServerRequestInterface $request = null)
327 {
328 if ($request === null) {
329 // Missing argument? This method must have been called from outside.
330 // Method will be protected and $request mandatory in v10, giving core freedom to move stuff around
331 // New v10 signature: "protected function main(ServerRequestInterface $request)"
332 // @deprecated since TYPO3 v9, method argument $request will be set to mandatory
333 $request = $GLOBALS['TYPO3_REQUEST'];
334 }
335
336 $backendUser = $this->getBackendUserAuthentication();
337 $lang = $this->getLanguageService();
338 // Loading current page record and checking access:
339 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
340 $access = is_array($this->pageinfo);
341
342 // Start document template object
343 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Instantiation will be removed.
344 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
345
346 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
347 $calcPerms = $backendUser->calcPerms($this->pageinfo);
348 $userCanEditPage = $calcPerms & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int)$this->pageinfo['editlock'] === 0);
349 if ($userCanEditPage) {
350 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
351 PageActions.setPageId(' . (int)$this->id . ');
352 }');
353 }
354 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip');
355 // Apply predefined values for hidden checkboxes
356 // Set predefined value for DisplayBigControlPanel:
357 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') {
358 $this->MOD_SETTINGS['bigControlPanel'] = true;
359 } elseif ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'deactivated') {
360 $this->MOD_SETTINGS['bigControlPanel'] = false;
361 }
362 // Set predefined value for Clipboard:
363 if ($this->modTSconfig['properties']['enableClipBoard'] === 'activated') {
364 $this->MOD_SETTINGS['clipBoard'] = true;
365 } elseif ($this->modTSconfig['properties']['enableClipBoard'] === 'deactivated') {
366 $this->MOD_SETTINGS['clipBoard'] = false;
367 } else {
368 if ($this->MOD_SETTINGS['clipBoard'] === null) {
369 $this->MOD_SETTINGS['clipBoard'] = true;
370 }
371 }
372
373 // Initialize the dblist object:
374 $dblist = GeneralUtility::makeInstance(DatabaseRecordList::class);
375 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
376 $dblist->script = (string)$uriBuilder->buildUriFromRoute('web_list');
377 $dblist->calcPerms = $calcPerms;
378 $dblist->thumbs = $backendUser->uc['thumbnailsByDefault'];
379 $dblist->returnUrl = $this->returnUrl;
380 $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0;
381 $dblist->showClipboard = 1;
382 $dblist->disableSingleTableView = $this->modTSconfig['properties']['disableSingleTableView'];
383 $dblist->listOnlyInSingleTableMode = $this->modTSconfig['properties']['listOnlyInSingleTableView'];
384 $dblist->hideTables = $this->modTSconfig['properties']['hideTables'];
385 $dblist->hideTranslations = $this->modTSconfig['properties']['hideTranslations'];
386 $dblist->tableTSconfigOverTCA = $this->modTSconfig['properties']['table.'];
387 $dblist->allowedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['allowedNewTables'], true);
388 $dblist->deniedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['deniedNewTables'], true);
389 $dblist->pageRow = $this->pageinfo;
390 $dblist->counter++;
391 $dblist->MOD_MENU = ['bigControlPanel' => '', 'clipBoard' => ''];
392 $dblist->modTSconfig = $this->modTSconfig;
393 $clickTitleMode = trim($this->modTSconfig['properties']['clickTitleMode']);
394 $dblist->clickTitleMode = $clickTitleMode === '' ? 'edit' : $clickTitleMode;
395 if (isset($this->modTSconfig['properties']['tableDisplayOrder.'])) {
396 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
397 $dblist->setTableDisplayOrder($typoScriptService->convertTypoScriptArrayToPlainArray($this->modTSconfig['properties']['tableDisplayOrder.']));
398 }
399 // Clipboard is initialized:
400 // Start clipboard
401 $dblist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
402 // Initialize - reads the clipboard content from the user session
403 $dblist->clipObj->initializeClipboard();
404 // Clipboard actions are handled:
405 // CB is the clipboard command array
406 $CB = GeneralUtility::_GET('CB');
407 if ($this->cmd === 'setCB') {
408 // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked.
409 // By merging we get a full array of checked/unchecked elements
410 // This is set to the 'el' array of the CB after being parsed so only the table in question is registered.
411 $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(GeneralUtility::_POST('CBH'), (array)GeneralUtility::_POST('CBC')), $this->cmd_table);
412 }
413 if (!$this->MOD_SETTINGS['clipBoard']) {
414 // If the clipboard is NOT shown, set the pad to 'normal'.
415 $CB['setP'] = 'normal';
416 }
417 // Execute commands.
418 $dblist->clipObj->setCmd($CB);
419 // Clean up pad
420 $dblist->clipObj->cleanCurrent();
421 // Save the clipboard content
422 $dblist->clipObj->endClipboard();
423 // This flag will prevent the clipboard panel in being shown.
424 // It is set, if the clickmenu-layer is active AND the extended view is not enabled.
425 $dblist->dontShowClipControlPanels = ($dblist->clipObj->current === 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
426 // 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:
427 if ($access || ($this->id === 0 && $this->search_levels !== 0 && $this->search_field !== '')) {
428 // Deleting records...:
429 // 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.
430 if ($this->cmd === 'delete') {
431 $items = $dblist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), $this->cmd_table, 1);
432 if (!empty($items)) {
433 $cmd = [];
434 foreach ($items as $iK => $value) {
435 $iKParts = explode('|', $iK);
436 $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1;
437 }
438 $tce = GeneralUtility::makeInstance(DataHandler::class);
439 $tce->start([], $cmd);
440 $tce->process_cmdmap();
441 if (isset($cmd['pages'])) {
442 BackendUtility::setUpdateSignal('updatePageTree');
443 }
444 $tce->printLogErrorMessages();
445 }
446 }
447 // Initialize the listing object, dblist, for rendering the list:
448 $this->pointer = max(0, (int)$this->pointer);
449 $dblist->start($this->id, $this->table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit);
450 $dblist->setDispFields();
451 // Render the list of tables:
452 $dblist->generateList();
453 $listUrl = $dblist->listURL();
454 // Add JavaScript functions to the page:
455
456 $this->moduleTemplate->addJavaScriptCode(
457 'RecordListInlineJS',
458 '
459 function jumpExt(URL,anchor) {
460 var anc = anchor?anchor:"";
461 window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
462 return false;
463 }
464 function jumpSelf(URL) {
465 window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
466 return false;
467 }
468 function jumpToUrl(URL) {
469 window.location.href = URL;
470 return false;
471 }
472
473 function setHighlight(id) {
474 top.fsMod.recentIds["web"] = id;
475 top.fsMod.navFrameHighlightedID["web"] = top.fsMod.currentBank + "_" + id; // For highlighting
476
477 if (top.nav_frame && top.nav_frame.refresh_nav) {
478 top.nav_frame.refresh_nav();
479 }
480 }
481 ' . $this->moduleTemplate->redirectUrls($listUrl) . '
482 ' . $dblist->CBfunctions() . '
483 function editRecords(table,idList,addParams,CBflag) {
484 window.location.href="' . (string)$uriBuilder->buildUriFromRoute('record_edit', ['returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]) . '&edit["+table+"]["+idList+"]=edit"+addParams;
485 }
486 function editList(table,idList) {
487 var list="";
488
489 // Checking how many is checked, how many is not
490 var pointer=0;
491 var pos = idList.indexOf(",");
492 while (pos!=-1) {
493 if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
494 list+=idList.substr(pointer,pos-pointer)+",";
495 }
496 pointer=pos+1;
497 pos = idList.indexOf(",",pointer);
498 }
499 if (cbValue(table+"|"+idList.substr(pointer))) {
500 list+=idList.substr(pointer)+",";
501 }
502
503 return list ? list : idList;
504 }
505
506 if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
507 '
508 );
509
510 // Setting up the context sensitive menu:
511 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
512 }
513 // access
514 // Begin to compile the whole page, starting out with page header:
515 if (!$this->id) {
516 $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
517 } else {
518 $title = $this->pageinfo['title'];
519 }
520 $this->body = $this->moduleTemplate->header($title);
521
522 // Additional header content
523 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook'] ?? [] as $hook) {
524 $params = [
525 'request' => $request,
526 ];
527 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10: Handing over $this as second constructor argument will be changed to $null = null;
528 $this->body .= GeneralUtility::callUserFunction($hook, $params, $this);
529 }
530
531 $this->moduleTemplate->setTitle($title);
532
533 $output = '';
534 // Show the selector to add page translations and the list of translations of the current page
535 // but only when in "default" mode
536 if ($this->id && !$dblist->csvOutput && !$this->search_field && !$this->cmd && !$this->table) {
537 $output .= $this->languageSelector($this->id);
538 $pageTranslationsDatabaseRecordList = clone $dblist;
539 $pageTranslationsDatabaseRecordList->listOnlyInSingleTableMode = false;
540 $pageTranslationsDatabaseRecordList->disableSingleTableView = true;
541 $pageTranslationsDatabaseRecordList->deniedNewTables = ['pages'];
542 $pageTranslationsDatabaseRecordList->hideTranslations = '';
543 $pageTranslationsDatabaseRecordList->iLimit = $pageTranslationsDatabaseRecordList->itemsLimitPerTable;
544 $pageTranslationsDatabaseRecordList->showOnlyTranslatedRecords(true);
545 $output .= $pageTranslationsDatabaseRecordList->getTable('pages', $this->id);
546 }
547
548 if (!empty($dblist->HTMLcode)) {
549 $output .= $dblist->HTMLcode;
550 } else {
551 $flashMessage = GeneralUtility::makeInstance(
552 FlashMessage::class,
553 $lang->getLL('noRecordsOnThisPage'),
554 '',
555 FlashMessage::INFO
556 );
557 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
558 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
559 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */
560 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
561 $defaultFlashMessageQueue->enqueue($flashMessage);
562 }
563
564 $this->body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">';
565 $this->body .= $output;
566 $this->body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
567 // If a listing was produced, create the page footer with search form etc:
568 if ($dblist->HTMLcode) {
569 // Making field select box (when extended view for a single table is enabled):
570 if ($dblist->table) {
571 $this->body .= $dblist->fieldSelectBox($dblist->table);
572 }
573 // Adding checkbox options for extended listing and clipboard display:
574 $this->body .= '
575
576 <!--
577 Listing options for extended view and clipboard view
578 -->
579 <div class="typo3-listOptions">
580 <form action="" method="post">';
581
582 // Add "display bigControlPanel" checkbox:
583 if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'selectable') {
584 $this->body .= '<div class="checkbox">' .
585 '<label for="checkLargeControl">' .
586 BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $this->MOD_SETTINGS['bigControlPanel'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLargeControl"') .
587 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('largeControl'))) .
588 '</label>' .
589 '</div>';
590 }
591
592 // Add "clipboard" checkbox:
593 if ($this->modTSconfig['properties']['enableClipBoard'] === 'selectable') {
594 if ($dblist->showClipboard) {
595 $this->body .= '<div class="checkbox">' .
596 '<label for="checkShowClipBoard">' .
597 BackendUtility::getFuncCheck($this->id, 'SET[clipBoard]', $this->MOD_SETTINGS['clipBoard'], '', $this->table ? '&table=' . $this->table : '', 'id="checkShowClipBoard"') .
598 BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('showClipBoard'))) .
599 '</label>' .
600 '</div>';
601 }
602 }
603
604 $this->body .= '
605 </form>
606 </div>';
607 }
608 // Printing clipboard if enabled
609 if ($this->MOD_SETTINGS['clipBoard'] && $dblist->showClipboard && ($dblist->HTMLcode || $dblist->clipObj->hasElements())) {
610 $this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>';
611 }
612 // Additional footer content
613 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'] ?? [] as $hook) {
614 $params = [
615 'request' => $request,
616 ];
617 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10: Handing over $this as second constructor argument will be changed to $null = null;
618 $this->body .= GeneralUtility::callUserFunction($hook, $params, $this);
619 }
620 // Setting up the buttons for docheader
621 $dblist->getDocHeaderButtons($this->moduleTemplate);
622 // search box toolbar
623 if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dblist->HTMLcode || !empty($dblist->searchString))) {
624 $this->content = $dblist->getSearchBox();
625 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
626
627 $searchButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeLinkButton();
628 $searchButton
629 ->setHref('#')
630 ->setClasses('t3js-toggle-search-toolbox')
631 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
632 ->setIcon($this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL));
633 $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->addButton(
634 $searchButton,
635 ButtonBar::BUTTON_POSITION_LEFT,
636 90
637 );
638 }
639
640 if ($this->pageinfo) {
641 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
642 }
643
644 // Build the <body> for the module
645 $this->content .= $this->body;
646 }
647
648 /**
649 * Injects the request object for the current request or subrequest
650 * Simply calls main() and init() and outputs the content
651 *
652 * @param ServerRequestInterface $request the current request
653 * @return ResponseInterface the response with the content
654 */
655 public function mainAction(ServerRequestInterface $request): ResponseInterface
656 {
657 $this->site = $request->getAttribute('site');
658 $this->siteLanguages = $this->site->getAvailableLanguages($this->getBackendUserAuthentication(), false, (int)$this->id);
659 BackendUtility::lockRecords();
660 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Can be removed along with $this->doc.
661 $GLOBALS['SOBE'] = $this;
662 $this->init();
663 $this->clearCache();
664 $this->main($request);
665 $this->moduleTemplate->setContent($this->content);
666 return new HtmlResponse($this->moduleTemplate->renderContent());
667 }
668
669 /**
670 * Make selector box for creating new translation in a language
671 * Displays only languages which are not yet present for the current page and
672 * that are not disabled with page TS.
673 *
674 * @param int $id Page id for which to create a new translation record of pages
675 * @return string <select> HTML element (if there were items for the box anyways...)
676 */
677 protected function languageSelector(int $id): string
678 {
679 if (!$this->getBackendUserAuthentication()->check('tables_modify', 'pages')) {
680 return '';
681 }
682 $availableTranslations = [];
683 foreach ($this->siteLanguages as $siteLanguage) {
684 if ($siteLanguage->getLanguageId() === 0) {
685 continue;
686 }
687 $availableTranslations[$siteLanguage->getLanguageId()] = $siteLanguage->getTitle();
688 }
689 // Then, subtract the languages which are already on the page:
690 $localizationParentField = $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'];
691 $languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField'];
692 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
693 $queryBuilder->getRestrictions()->removeAll()
694 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
695 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
696 $statement = $queryBuilder->select('uid', $languageField)
697 ->from('pages')
698 ->where(
699 $queryBuilder->expr()->eq(
700 $localizationParentField,
701 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
702 )
703 )
704 ->execute();
705 while ($pageTranslation = $statement->fetch()) {
706 unset($availableTranslations[(int)$pageTranslation[$languageField]]);
707 }
708 // If any languages are left, make selector:
709 if (!empty($availableTranslations)) {
710 $output = '<option value="">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:new_language')) . '</option>';
711 foreach ($availableTranslations as $languageUid => $languageTitle) {
712 // Build localize command URL to DataHandler (tce_db)
713 // which redirects to FormEngine (record_edit)
714 // which, when finished editing should return back to the current page (returnUrl)
715 $parameters = [
716 'justLocalized' => 'pages:' . $id . ':' . $languageUid,
717 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
718 ];
719 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
720 $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', $parameters);
721 $targetUrl = BackendUtility::getLinkToDataHandlerAction(
722 '&cmd[pages][' . $id . '][localize]=' . $languageUid,
723 $redirectUrl
724 );
725
726 $output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>';
727 }
728
729 return '<div class="form-inline form-inline-spaced">'
730 . '<div class="form-group">'
731 . '<select class="form-control input-sm" name="createNewLanguage" onchange="window.location.href=this.options[this.selectedIndex].value">'
732 . $output
733 . '</select></div></div>';
734 }
735 return '';
736 }
737
738 /**
739 * @return ModuleTemplate
740 */
741 protected function getModuleTemplate(): ModuleTemplate
742 {
743 return $this->moduleTemplate;
744 }
745
746 /**
747 * @return BackendUserAuthentication
748 */
749 protected function getBackendUserAuthentication(): BackendUserAuthentication
750 {
751 return $GLOBALS['BE_USER'];
752 }
753
754 /**
755 * @return LanguageService
756 */
757 protected function getLanguageService(): LanguageService
758 {
759 return $GLOBALS['LANG'];
760 }
761
762 /**
763 * @return PageRenderer
764 */
765 protected function getPageRenderer(): PageRenderer
766 {
767 if ($this->pageRenderer === null) {
768 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
769 }
770 return $this->pageRenderer;
771 }
772 }