2 namespace TYPO3\CMS\Recordlist
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use Psr\Http\Message\ResponseInterface
;
18 use Psr\Http\Message\ServerRequestInterface
;
19 use TYPO3\CMS\Backend\Clipboard\Clipboard
;
20 use TYPO3\CMS\Backend\Template\Components\ButtonBar
;
21 use TYPO3\CMS\Backend\Template\DocumentTemplate
;
22 use TYPO3\CMS\Backend\Template\ModuleTemplate
;
23 use TYPO3\CMS\Backend\Utility\BackendUtility
;
24 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication
;
25 use TYPO3\CMS\Core\Database\ConnectionPool
;
26 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
;
27 use TYPO3\CMS\Core\DataHandling\DataHandler
;
28 use TYPO3\CMS\Core\Imaging\Icon
;
29 use TYPO3\CMS\Core\Imaging\IconFactory
;
30 use TYPO3\CMS\Core\Localization\LanguageService
;
31 use TYPO3\CMS\Core\Messaging\FlashMessage
;
32 use TYPO3\CMS\Core\Messaging\FlashMessageService
;
33 use TYPO3\CMS\Core\Page\PageRenderer
;
34 use TYPO3\CMS\Core\Type\Bitmask\Permission
;
35 use TYPO3\CMS\Core\TypoScript\TypoScriptService
;
36 use TYPO3\CMS\Core\Utility\GeneralUtility
;
37 use TYPO3\CMS\Core\Versioning\VersionState
;
40 * Script Class for the Web > List module; rendering the listing of records on a page
45 * Page Id for which to make the listing
52 * Pointer - for browsing list of records.
66 * Which table to make extended listing for
84 public $search_levels;
101 * Clear-cache flag - if set, clears page cache for current id.
108 * Command: Eg. "delete" or "setCB" (for DataHandler / clipboard operations)
115 * Table on which the cmd-action is performed.
122 * Page select perms clause
126 public $perms_clause;
136 * Current ids page record
143 * Document template object
145 * @var DocumentTemplate
154 public $MOD_MENU = [];
157 * Module settings (session variable)
161 public $MOD_SETTINGS = [];
164 * Module output accumulation
171 * The name of the module
175 protected $moduleName = 'web_list';
185 protected $pageRenderer = null;
190 protected $iconFactory;
193 * ModuleTemplate object
195 * @var ModuleTemplate
197 protected $moduleTemplate;
202 public function __construct()
204 $this->moduleTemplate
= GeneralUtility
::makeInstance(ModuleTemplate
::class);
205 $this->getLanguageService()->includeLLFile('EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf');
206 $this->moduleTemplate
->getPageRenderer()->loadJquery();
207 $this->moduleTemplate
->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
208 $this->moduleTemplate
->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Recordlist');
212 * Initializing the module
214 public function init()
216 $this->iconFactory
= GeneralUtility
::makeInstance(IconFactory
::class);
217 $backendUser = $this->getBackendUserAuthentication();
218 $this->perms_clause
= $backendUser->getPagePermsClause(Permission
::PAGE_SHOW
);
220 $sessionData = $backendUser->getSessionData(__CLASS__
);
221 $this->search_field
= !empty($sessionData['search_field']) ?
$sessionData['search_field'] : '';
223 $this->id
= (int)GeneralUtility
::_GP('id');
224 $this->pointer
= GeneralUtility
::_GP('pointer');
225 $this->imagemode
= GeneralUtility
::_GP('imagemode');
226 $this->table
= GeneralUtility
::_GP('table');
227 $this->search_field
= GeneralUtility
::_GP('search_field');
228 $this->search_levels
= (int)GeneralUtility
::_GP('search_levels');
229 $this->showLimit
= GeneralUtility
::_GP('showLimit');
230 $this->returnUrl
= GeneralUtility
::sanitizeLocalUrl(GeneralUtility
::_GP('returnUrl'));
231 $this->clear_cache
= GeneralUtility
::_GP('clear_cache');
232 $this->cmd
= GeneralUtility
::_GP('cmd');
233 $this->cmd_table
= GeneralUtility
::_GP('cmd_table');
234 $sessionData['search_field'] = $this->search_field
;
237 // Store session data
238 $backendUser->setAndSaveSessionData(self
::class, $sessionData);
239 $this->getPageRenderer()->addInlineLanguageLabelFile('EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf');
243 * Initialize function menu array
245 public function menuConfig()
249 'bigControlPanel' => '',
252 // Loading module configuration:
253 $this->modTSconfig
= BackendUtility
::getModTSconfig($this->id
, 'mod.' . $this->moduleName
);
254 // Clean up settings:
255 $this->MOD_SETTINGS
= BackendUtility
::getModuleData($this->MOD_MENU
, GeneralUtility
::_GP('SET'), $this->moduleName
);
259 * Clears page cache for the current id, $this->id
261 public function clearCache()
263 if ($this->clear_cache
) {
264 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
266 $tce->clear_cacheCmd($this->id
);
271 * Main function, starting the rendering of the list.
273 public function main()
275 $backendUser = $this->getBackendUserAuthentication();
276 $lang = $this->getLanguageService();
277 // Loading current page record and checking access:
278 $this->pageinfo
= BackendUtility
::readPageAccess($this->id
, $this->perms_clause
);
279 $access = is_array($this->pageinfo
);
280 // Start document template object:
281 // We need to keep this due to deeply nested dependencies
282 $this->doc
= GeneralUtility
::makeInstance(DocumentTemplate
::class);
284 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
285 $calcPerms = $backendUser->calcPerms($this->pageinfo
);
286 $userCanEditPage = $calcPerms & Permission
::PAGE_EDIT
&& !empty($this->id
) && ($backendUser->isAdmin() ||
(int)$this->pageinfo
['editlock'] === 0);
287 if ($userCanEditPage) {
288 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
289 PageActions.setPageId(' . (int)$this->id
. ');
290 PageActions.initializePageTitleRenaming();
293 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip');
294 // Apply predefined values for hidden checkboxes
295 // Set predefined value for DisplayBigControlPanel:
296 if ($this->modTSconfig
['properties']['enableDisplayBigControlPanel'] === 'activated') {
297 $this->MOD_SETTINGS
['bigControlPanel'] = true;
298 } elseif ($this->modTSconfig
['properties']['enableDisplayBigControlPanel'] === 'deactivated') {
299 $this->MOD_SETTINGS
['bigControlPanel'] = false;
301 // Set predefined value for Clipboard:
302 if ($this->modTSconfig
['properties']['enableClipBoard'] === 'activated') {
303 $this->MOD_SETTINGS
['clipBoard'] = true;
304 } elseif ($this->modTSconfig
['properties']['enableClipBoard'] === 'deactivated') {
305 $this->MOD_SETTINGS
['clipBoard'] = false;
307 if ($this->MOD_SETTINGS
['clipBoard'] === null) {
308 $this->MOD_SETTINGS
['clipBoard'] = true;
312 // Initialize the dblist object:
313 /** @var $dblist RecordList\DatabaseRecordList */
314 $dblist = GeneralUtility
::makeInstance(RecordList\DatabaseRecordList
::class);
315 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
316 $uriBuilder = GeneralUtility
::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder
::class);
317 $dblist->script
= (string)$uriBuilder->buildUriFromRoute('web_list');
318 $dblist->calcPerms
= $calcPerms;
319 $dblist->thumbs
= $backendUser->uc
['thumbnailsByDefault'];
320 $dblist->returnUrl
= $this->returnUrl
;
321 $dblist->allFields
= $this->MOD_SETTINGS
['bigControlPanel'] ||
$this->table ?
1 : 0;
322 $dblist->showClipboard
= 1;
323 $dblist->disableSingleTableView
= $this->modTSconfig
['properties']['disableSingleTableView'];
324 $dblist->listOnlyInSingleTableMode
= $this->modTSconfig
['properties']['listOnlyInSingleTableView'];
325 $dblist->hideTables
= $this->modTSconfig
['properties']['hideTables'];
326 $dblist->hideTranslations
= $this->modTSconfig
['properties']['hideTranslations'];
327 $dblist->tableTSconfigOverTCA
= $this->modTSconfig
['properties']['table.'];
328 $dblist->allowedNewTables
= GeneralUtility
::trimExplode(',', $this->modTSconfig
['properties']['allowedNewTables'], true);
329 $dblist->deniedNewTables
= GeneralUtility
::trimExplode(',', $this->modTSconfig
['properties']['deniedNewTables'], true);
330 $dblist->newWizards
= $this->modTSconfig
['properties']['newWizards'] ?
1 : 0;
331 $dblist->pageRow
= $this->pageinfo
;
333 $dblist->MOD_MENU
= ['bigControlPanel' => '', 'clipBoard' => ''];
334 $dblist->modTSconfig
= $this->modTSconfig
;
335 $clickTitleMode = trim($this->modTSconfig
['properties']['clickTitleMode']);
336 $dblist->clickTitleMode
= $clickTitleMode === '' ?
'edit' : $clickTitleMode;
337 if (isset($this->modTSconfig
['properties']['tableDisplayOrder.'])) {
338 $typoScriptService = GeneralUtility
::makeInstance(TypoScriptService
::class);
339 $dblist->setTableDisplayOrder($typoScriptService->convertTypoScriptArrayToPlainArray($this->modTSconfig
['properties']['tableDisplayOrder.']));
341 // Clipboard is initialized:
343 $dblist->clipObj
= GeneralUtility
::makeInstance(Clipboard
::class);
344 // Initialize - reads the clipboard content from the user session
345 $dblist->clipObj
->initializeClipboard();
346 // Clipboard actions are handled:
347 // CB is the clipboard command array
348 $CB = GeneralUtility
::_GET('CB');
349 if ($this->cmd
=== 'setCB') {
350 // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked.
351 // By merging we get a full array of checked/unchecked elements
352 // This is set to the 'el' array of the CB after being parsed so only the table in question is registered.
353 $CB['el'] = $dblist->clipObj
->cleanUpCBC(array_merge(GeneralUtility
::_POST('CBH'), (array)GeneralUtility
::_POST('CBC')), $this->cmd_table
);
355 if (!$this->MOD_SETTINGS
['clipBoard']) {
356 // If the clipboard is NOT shown, set the pad to 'normal'.
357 $CB['setP'] = 'normal';
360 $dblist->clipObj
->setCmd($CB);
362 $dblist->clipObj
->cleanCurrent();
363 // Save the clipboard content
364 $dblist->clipObj
->endClipboard();
365 // This flag will prevent the clipboard panel in being shown.
366 // It is set, if the clickmenu-layer is active AND the extended view is not enabled.
367 $dblist->dontShowClipControlPanels
= ($dblist->clipObj
->current
=== 'normal' && !$this->modTSconfig
['properties']['showClipControlPanelsDespiteOfCMlayers']);
368 // 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:
369 if ($access ||
($this->id
=== 0 && $this->search_levels
!== 0 && $this->search_field
!== '')) {
370 // Deleting records...:
371 // 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.
372 if ($this->cmd
=== 'delete') {
373 $items = $dblist->clipObj
->cleanUpCBC(GeneralUtility
::_POST('CBC'), $this->cmd_table
, 1);
374 if (!empty($items)) {
376 foreach ($items as $iK => $value) {
377 $iKParts = explode('|', $iK);
378 $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1;
380 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
381 $tce->start([], $cmd);
382 $tce->process_cmdmap();
383 if (isset($cmd['pages'])) {
384 BackendUtility
::setUpdateSignal('updatePageTree');
386 $tce->printLogErrorMessages();
389 // Initialize the listing object, dblist, for rendering the list:
390 $this->pointer
= max(0, (int)$this->pointer
);
391 $dblist->start($this->id
, $this->table
, $this->pointer
, $this->search_field
, $this->search_levels
, $this->showLimit
);
392 $dblist->setDispFields();
393 // Render the list of tables:
394 $dblist->generateList();
395 $listUrl = $dblist->listURL();
396 // Add JavaScript functions to the page:
398 $this->moduleTemplate
->addJavaScriptCode(
399 'RecordListInlineJS',
401 function jumpExt(URL,anchor) { //
402 var anc = anchor?anchor:"";
403 window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
406 function jumpSelf(URL) { //
407 window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
410 function jumpToUrl(URL) {
411 window.location.href = URL;
415 function setHighlight(id) { //
416 top.fsMod.recentIds["web"]=id;
417 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
419 if (top.nav_frame && top.nav_frame.refresh_nav) {
420 top.nav_frame.refresh_nav();
423 ' . $this->moduleTemplate
->redirectUrls($listUrl) . '
424 ' . $dblist->CBfunctions() . '
425 function editRecords(table,idList,addParams,CBflag) { //
426 window.location.href="' . (string)$uriBuilder->buildUriFromRoute('record_edit', ['returnUrl' => GeneralUtility
::getIndpEnv('REQUEST_URI')]) . '&edit["+table+"]["+idList+"]=edit"+addParams;
428 function editList(table,idList) { //
431 // Checking how many is checked, how many is not
433 var pos = idList.indexOf(",");
435 if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
436 list+=idList.substr(pointer,pos-pointer)+",";
439 pos = idList.indexOf(",",pointer);
441 if (cbValue(table+"|"+idList.substr(pointer))) {
442 list+=idList.substr(pointer)+",";
445 return list ? list : idList;
448 if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id
. ';
452 // Setting up the context sensitive menu:
453 $this->moduleTemplate
->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
456 // Begin to compile the whole page, starting out with page header:
458 $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
460 $title = $this->pageinfo
['title'];
462 $this->body
= $this->moduleTemplate
->header($title);
463 $this->moduleTemplate
->setTitle($title);
466 // Show the selector to add page translations and the list of translations of the current page
467 // but only when in "default" mode
468 if ($this->id
&& !$dblist->csvOutput
&& !$this->search_field
&& !$this->cmd
&& !$this->table
) {
469 $output .= $this->languageSelector($this->id
);
470 $pageTranslationsDatabaseRecordList = clone $dblist;
471 $pageTranslationsDatabaseRecordList->listOnlyInSingleTableMode
= false;
472 $pageTranslationsDatabaseRecordList->disableSingleTableView
= true;
473 $pageTranslationsDatabaseRecordList->deniedNewTables
= ['pages'];
474 $pageTranslationsDatabaseRecordList->hideTranslations
= '';
475 $pageTranslationsDatabaseRecordList->iLimit
= $pageTranslationsDatabaseRecordList->itemsLimitPerTable
;
476 $pageTranslationsDatabaseRecordList->showOnlyTranslatedRecords(true);
477 $output .= $pageTranslationsDatabaseRecordList->getTable('pages', $this->id
);
480 if (!empty($dblist->HTMLcode
)) {
481 $output .= $dblist->HTMLcode
;
483 $flashMessage = GeneralUtility
::makeInstance(
485 $lang->getLL('noRecordsOnThisPage'),
489 /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
490 $flashMessageService = GeneralUtility
::makeInstance(FlashMessageService
::class);
491 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
492 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
493 $defaultFlashMessageQueue->enqueue($flashMessage);
496 $this->body
.= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">';
497 $this->body
.= $output;
498 $this->body
.= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
499 // If a listing was produced, create the page footer with search form etc:
500 if ($dblist->HTMLcode
) {
501 // Making field select box (when extended view for a single table is enabled):
502 if ($dblist->table
) {
503 $this->body
.= $dblist->fieldSelectBox($dblist->table
);
505 // Adding checkbox options for extended listing and clipboard display:
509 Listing options for extended view and clipboard view
511 <div class="typo3-listOptions">
512 <form action="" method="post">';
514 // Add "display bigControlPanel" checkbox:
515 if ($this->modTSconfig
['properties']['enableDisplayBigControlPanel'] === 'selectable') {
516 $this->body
.= '<div class="checkbox">' .
517 '<label for="checkLargeControl">' .
518 BackendUtility
::getFuncCheck($this->id
, 'SET[bigControlPanel]', $this->MOD_SETTINGS
['bigControlPanel'], '', $this->table ?
'&table=' . $this->table
: '', 'id="checkLargeControl"') .
519 BackendUtility
::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('largeControl'))) .
524 // Add "clipboard" checkbox:
525 if ($this->modTSconfig
['properties']['enableClipBoard'] === 'selectable') {
526 if ($dblist->showClipboard
) {
527 $this->body
.= '<div class="checkbox">' .
528 '<label for="checkShowClipBoard">' .
529 BackendUtility
::getFuncCheck($this->id
, 'SET[clipBoard]', $this->MOD_SETTINGS
['clipBoard'], '', $this->table ?
'&table=' . $this->table
: '', 'id="checkShowClipBoard"') .
530 BackendUtility
::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('showClipBoard'))) .
540 // Printing clipboard if enabled
541 if ($this->MOD_SETTINGS
['clipBoard'] && $dblist->showClipboard
&& ($dblist->HTMLcode ||
$dblist->clipObj
->hasElements())) {
542 $this->body
.= '<div class="db_list-dashboard">' . $dblist->clipObj
->printClipboard() . '</div>';
544 // Additional footer content
545 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'] ??
[] as $hook) {
547 $this->body
.= GeneralUtility
::callUserFunction($hook, $params, $this);
549 // Setting up the buttons for docheader
550 $dblist->getDocHeaderButtons($this->moduleTemplate
);
552 if (!$this->modTSconfig
['properties']['disableSearchBox'] && ($dblist->HTMLcode ||
!empty($dblist->searchString
))) {
553 $this->content
= $dblist->getSearchBox();
554 $this->moduleTemplate
->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
556 $searchButton = $this->moduleTemplate
->getDocHeaderComponent()->getButtonBar()->makeLinkButton();
559 ->setClasses('t3js-toggle-search-toolbox')
560 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
561 ->setIcon($this->iconFactory
->getIcon('actions-search', Icon
::SIZE_SMALL
));
562 $this->moduleTemplate
->getDocHeaderComponent()->getButtonBar()->addButton(
564 ButtonBar
::BUTTON_POSITION_LEFT
,
569 if ($this->pageinfo
) {
570 $this->moduleTemplate
->getDocHeaderComponent()->setMetaInformation($this->pageinfo
);
573 // Build the <body> for the module
574 $this->content
.= $this->body
;
578 * Injects the request object for the current request or subrequest
579 * Simply calls main() and init() and outputs the content
581 * @param ServerRequestInterface $request the current request
582 * @param ResponseInterface $response
583 * @return ResponseInterface the response with the content
585 public function mainAction(ServerRequestInterface
$request, ResponseInterface
$response)
587 BackendUtility
::lockRecords();
588 $GLOBALS['SOBE'] = $this;
592 $this->moduleTemplate
->setContent($this->content
);
593 $response->getBody()->write($this->moduleTemplate
->renderContent());
598 * Make selector box for creating new translation in a language
599 * Displays only languages which are not yet present for the current page and
600 * that are not disabled with page TS.
602 * @param int $id Page id for which to create a new translation record of pages
603 * @return string <select> HTML element (if there were items for the box anyways...)
605 protected function languageSelector(int $id): string
607 if ($this->getBackendUserAuthentication()->check('tables_modify', 'pages')) {
609 $queryBuilder = GeneralUtility
::makeInstance(ConnectionPool
::class)->getQueryBuilderForTable('sys_language');
610 $queryBuilder->getRestrictions()->removeAll();
611 $queryBuilder->getRestrictions()->add(GeneralUtility
::makeInstance(HiddenRestriction
::class));
612 $statement = $queryBuilder->select('uid', 'title')
613 ->from('sys_language')
616 $availableTranslations = [];
617 while ($row = $statement->fetch()) {
618 if ($this->getBackendUserAuthentication()->checkLanguageAccess($row['uid'])) {
619 $availableTranslations[(int)$row['uid']] = $row['title'];
622 // Then, subtract the languages which are already on the page:
623 $localizationParentField = $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'];
624 $languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField'];
625 $queryBuilder = GeneralUtility
::makeInstance(ConnectionPool
::class)->getQueryBuilderForTable('sys_language');
626 $queryBuilder->getRestrictions()->removeAll();
627 $queryBuilder->select('sys_language.uid AS uid', 'sys_language.title AS title')
628 ->from('sys_language')
633 $queryBuilder->expr()->eq('sys_language.uid', $queryBuilder->quoteIdentifier('pages.' . $languageField))
636 $queryBuilder->expr()->eq(
638 $queryBuilder->createNamedParameter(0, \PDO
::PARAM_INT
)
640 $queryBuilder->expr()->eq(
641 'pages.' . $localizationParentField,
642 $queryBuilder->createNamedParameter($this->id
, \PDO
::PARAM_INT
)
644 $queryBuilder->expr()->orX(
645 $queryBuilder->expr()->gte(
647 $queryBuilder->createNamedParameter(
648 (string)new VersionState(VersionState
::DEFAULT_STATE
),
652 $queryBuilder->expr()->eq(
654 $queryBuilder->createNamedParameter($this->getBackendUserAuthentication()->workspace
, \PDO
::PARAM_INT
)
659 'pages.' . $languageField,
662 'sys_language.tstamp',
663 'sys_language.hidden',
664 'sys_language.title',
665 'sys_language.language_isocode',
666 'sys_language.static_lang_isocode',
668 'sys_language.sorting'
670 ->orderBy('sys_language.sorting');
671 if (!$this->getBackendUserAuthentication()->isAdmin()) {
672 $queryBuilder->andWhere(
673 $queryBuilder->expr()->eq(
674 'sys_language.hidden',
675 $queryBuilder->createNamedParameter(0, \PDO
::PARAM_INT
)
679 $statement = $queryBuilder->execute();
680 while ($row = $statement->fetch()) {
681 unset($availableTranslations[(int)$row['uid']]);
683 // Remove disallowed languages
684 if (!empty($availableTranslations)
685 && !$this->getBackendUserAuthentication()->isAdmin()
686 && $this->getBackendUserAuthentication()->groupData
['allowed_languages'] !== ''
688 $allowed_languages = array_flip(explode(',', $this->getBackendUserAuthentication()->groupData
['allowed_languages']));
689 if (!empty($allowed_languages)) {
690 foreach ($availableTranslations as $key => $value) {
691 if (!isset($allowed_languages[$key]) && $key != 0) {
692 unset($availableTranslations[$key]);
697 // Remove disabled languages
698 $modSharedTSconfig = BackendUtility
::getModTSconfig($id, 'mod.SHARED');
699 $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages'])
700 ? GeneralUtility
::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], true)
702 if (!empty($availableTranslations) && !empty($disableLanguages)) {
703 foreach ($disableLanguages as $language) {
704 if ($language != 0 && isset($availableTranslations[$language])) {
705 unset($availableTranslations[$language]);
709 // If any languages are left, make selector:
710 if (!empty($availableTranslations)) {
711 $output = '<option value="">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:new_language')) . '</option>';
712 foreach ($availableTranslations as $languageUid => $languageTitle) {
713 // Build localize command URL to DataHandler (tce_db)
714 // which redirects to FormEngine (record_edit)
715 // which, when finished editing should return back to the current page (returnUrl)
717 'justLocalized' => 'pages:' . $id . ':' . $languageUid,
718 'returnUrl' => GeneralUtility
::getIndpEnv('REQUEST_URI')
720 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
721 $uriBuilder = GeneralUtility
::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder
::class);
722 $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', $parameters);
723 $targetUrl = BackendUtility
::getLinkToDataHandlerAction(
724 '&cmd[pages][' . $id . '][localize]=' . $languageUid,
728 $output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>';
731 return '<div class="form-inline form-inline-spaced">'
732 . '<div class="form-group">'
733 . '<select class="form-control input-sm" name="createNewLanguage" onchange="window.location.href=this.options[this.selectedIndex].value">'
735 . '</select></div></div>';
742 * @return ModuleTemplate
744 public function getModuleTemplate()
746 return $this->moduleTemplate
;
750 * @return BackendUserAuthentication
752 protected function getBackendUserAuthentication()
754 return $GLOBALS['BE_USER'];
758 * @return LanguageService
760 protected function getLanguageService()
762 return $GLOBALS['LANG'];
766 * @return PageRenderer
768 protected function getPageRenderer()
770 if ($this->pageRenderer
=== null) {
771 $this->pageRenderer
= GeneralUtility
::makeInstance(PageRenderer
::class);
774 return $this->pageRenderer
;