/** * Returns a link with a command to TYPO3 Core Engine (tce_db.php) * * @see DocumentTemplate::issueCommand() * * @param string $parameters * @param string|int $redirectUrl * @return string */ public function render($parameters, $redirectUrl = '') { if (version_compare(TYPO3_branch, '7.0', '<')) { /** @var $documentTemplate \TYPO3\CMS\Backend\Template\DocumentTemplate */ $documentTemplate = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate'); $href = $documentTemplate->issueCommand('&' . $parameters, $redirectUrl); } else { $href = BackendUtility::getLinkToDataHandlerAction('&' . $parameters, $redirectUrl); } $this->tag->addAttribute('href', $href); $this->tag->setContent($this->renderChildren()); $this->tag->forceClosingTag(TRUE); return $this->tag->render(); }
/** * Creates button which is used to create copies of records.. * * @param array $defLanguageCount Numeric array with uids of tt_content elements in the default language * @param int $lP Sys language UID * @param int $colPos Column position * @return string "Copy languages" button, if available. */ public function newLanguageButton($defLanguageCount, $lP, $colPos = 0) { if (!$this->doEdit || !$lP) { return ''; } $copyFromLanguageMenu = ''; foreach ($this->getLanguagesToCopyFrom(GeneralUtility::_GP('id'), $lP, $colPos) as $languageId => $label) { $elementsInColumn = $languageId === 0 ? $defLanguageCount : $this->getElementsFromColumnAndLanguage(GeneralUtility::_GP('id'), $colPos, $languageId); if (!empty($elementsInColumn)) { $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getLinkToDataHandlerAction('&cmd[tt_content][' . implode(',', $elementsInColumn) . '][copyFromLanguage]=' . GeneralUtility::_GP('id') . ',' . $lP)) . '; return false;'; $copyFromLanguageMenu .= '<li><a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $this->languageFlag($languageId, false) . ' ' . htmlspecialchars($label) . '</a></li>' . LF; } } if ($copyFromLanguageMenu !== '') { $copyFromLanguageMenu = '<ul class="dropdown-menu">' . $copyFromLanguageMenu . '</ul>'; } if (!empty($defLanguageCount)) { $params = ''; foreach ($defLanguageCount as $uidVal) { $params .= '&cmd[tt_content][' . $uidVal . '][localize]=' . $lP; } // We have content in the default language, create a split button $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getLinkToDataHandlerAction($params)) . '; return false;'; $theNewButton = '<div class="btn-group"> <input class="btn btn-default" type="submit" onclick="' . htmlspecialchars($onClick) . '; return false;" value="' . htmlspecialchars($this->getLanguageService()->getLL('newPageContent_copyForLang', true) . ' [' . count($defLanguageCount) . ']') . '" />'; if ($copyFromLanguageMenu !== '' && $this->isColumnEmpty($colPos, $lP)) { $theNewButton .= '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . '<span class="caret"></span>' . '<span class="sr-only">Toggle Dropdown</span>' . '</button>' . $copyFromLanguageMenu; } $theNewButton .= '</div>'; } else { if ($copyFromLanguageMenu !== '' && $this->isColumnEmpty($colPos, $lP)) { $theNewButton = '<div class="btn-group">' . '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . $this->getLanguageService()->getLL('newPageContent_copyFromAnotherLang_button', true) . ' <span class="caret"></span>' . '</button>' . $copyFromLanguageMenu . '</div>'; } else { $theNewButton = ''; } } return '<div class="t3-page-lang-copyce">' . $theNewButton . '</div>'; }
/** * Draw the header for a single tt_content element * * @param array $row Record array * @param int $space Amount of pixel space above the header. UNUSED * @param bool $disableMoveAndNewButtons If set the buttons for creating new elements and moving up and down are not shown. * @param bool $langMode If set, we are in language mode and flags will be shown for languages * @param bool $dragDropEnabled If set the move button must be hidden * @return string HTML table with the record header. */ public function tt_content_drawHeader($row, $space = 0, $disableMoveAndNewButtons = false, $langMode = false, $dragDropEnabled = false) { $out = ''; // If show info is set...; if ($this->tt_contentConfig['showInfo'] && $this->getBackendUser()->recordEditAccessInternals('tt_content', $row)) { // Render control panel for the element: if ($this->tt_contentConfig['showCommands'] && $this->doEdit) { // Edit content element: $urlParameters = ['edit' => ['tt_content' => [$this->tt_contentData['nextThree'][$row['uid']] => 'edit']], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]; $url = BackendUtility::getModuleUrl('record_edit', $urlParameters) . '#element-tt_content-' . $row['uid']; $out .= '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->nextThree > 1 ? sprintf($this->getLanguageService()->getLL('nextThree'), $this->nextThree) : $this->getLanguageService()->getLL('edit')) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'; // Hide element: $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled']; if ($hiddenField && $GLOBALS['TCA']['tt_content']['columns'][$hiddenField] && (!$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude'] || $this->getBackendUser()->check('non_exclude_fields', 'tt_content:' . $hiddenField))) { if ($row[$hiddenField]) { $value = 0; $label = 'unHide'; } else { $value = 1; $label = 'hide'; } $params = '&data[tt_content][' . ($row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid']) . '][' . $hiddenField . ']=' . $value; $out .= '<a class="btn btn-default" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction($params)) . '" title="' . $this->getLanguageService()->getLL($label, true) . '">' . $this->iconFactory->getIcon('actions-edit-' . strtolower($label), Icon::SIZE_SMALL)->render() . '</a>'; } // Delete $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1'; $confirm = $this->getLanguageService()->getLL('deleteWarning') . BackendUtility::translationCount('tt_content', $row['uid'], ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord')); $out .= '<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction($params)) . '"' . ' data-severity="warning"' . ' data-title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_alt_doc.xlf:label.confirm.delete_record.title')) . '"' . ' data-content="' . htmlspecialchars($confirm) . '" ' . ' data-button-close-text="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:cancel')) . '"' . ' title="' . $this->getLanguageService()->getLL('deleteItem', true) . '">' . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() . '</a>'; if ($out && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) { $out = '<div class="btn-group btn-group-sm" role="group">' . $out . '</div>'; } else { $out = ''; } if (!$disableMoveAndNewButtons) { $moveButtonContent = ''; $displayMoveButtons = false; // Move element up: if ($this->tt_contentData['prev'][$row['uid']]) { $params = '&cmd[tt_content][' . $row['uid'] . '][move]=' . $this->tt_contentData['prev'][$row['uid']]; $moveButtonContent .= '<a class="btn btn-default" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction($params)) . '" title="' . $this->getLanguageService()->getLL('moveUp', true) . '">' . $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . '</a>'; if (!$dragDropEnabled) { $displayMoveButtons = true; } } else { $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>'; } // Move element down: if ($this->tt_contentData['next'][$row['uid']]) { $params = '&cmd[tt_content][' . $row['uid'] . '][move]= ' . $this->tt_contentData['next'][$row['uid']]; $moveButtonContent .= '<a class="btn btn-default" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction($params)) . '" title="' . $this->getLanguageService()->getLL('moveDown', true) . '">' . $this->iconFactory->getIcon('actions-move-down', Icon::SIZE_SMALL)->render() . '</a>'; if (!$dragDropEnabled) { $displayMoveButtons = true; } } else { $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>'; } if ($displayMoveButtons) { $out .= '<div class="btn-group btn-group-sm" role="group">' . $moveButtonContent . '</div>'; } } } } $allowDragAndDrop = $this->isDragAndDropAllowed($row); $additionalIcons = array(); if ($row['sys_language_uid'] > 0 && $this->checkIfTranslationsExistInLanguage([], (int) $row['sys_language_uid'])) { $disabledClickMenuItems = 'new,move'; $allowDragAndDrop = false; } $additionalIcons[] = $this->getIcon('tt_content', $row, $disabledClickMenuItems) . ' '; $additionalIcons[] = $langMode ? $this->languageFlag($row['sys_language_uid'], false) : ''; // Get record locking status: if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) { $additionalIcons[] = '<a href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;" title="' . htmlspecialchars($lockInfo['msg']) . '">' . $this->iconFactory->getIcon('status-warning-in-use', Icon::SIZE_SMALL)->render() . '</a>'; } // Call stats information hook if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { $_params = array('tt_content', $row['uid'], &$row); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { $additionalIcons[] = GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } // Wrap the whole header // NOTE: end-tag for <div class="t3-page-ce-body"> is in getTable_tt_content() return '<div class="t3-page-ce-header ' . ($allowDragAndDrop ? 't3-page-ce-header-draggable t3js-page-ce-draghandle' : '') . '"> <div class="t3-page-ce-header-icons-left">' . implode('', $additionalIcons) . '</div> <div class="t3-page-ce-header-icons-right">' . ($out ? '<div class="btn-toolbar">' . $out . '</div>' : '') . '</div> </div> <div class="t3-page-ce-body">'; }
/** * Administrative links for a table / record * * @param string $table Table name * @param array $row Record for which administrative links are generated. * @return string HTML link tags. */ public function adminLinks($table, $row) { // Edit link: $editUrl = BackendUtility::getModuleUrl('record_edit', ['edit' => [$table => [$row['uid'] => 'edit']], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]); $adminLink = '<a class="btn btn-default" href="' . htmlspecialchars($editUrl) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:cm.edit', true) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'; // Delete link: $adminLink .= '<a class="btn btn-default" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $row['uid'] . '][delete]=1')) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:cm.delete', true) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() . '</a>'; if ($table === 'pages') { // If another page module was specified, replace the default Page module with the new one $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule')); $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout'; // Perform some access checks: $a_wl = $GLOBALS['BE_USER']->check('modules', 'web_list'); $a_wp = $GLOBALS['BE_USER']->check('modules', $pageModule); $adminLink .= '<a class="btn btn-default" href="#" onclick="top.loadEditId(' . $row['uid'] . ');top.goToModule(' . GeneralUtility::quoteJSvalue($pageModule) . '); return false;">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-page-open', Icon::SIZE_SMALL)->render() . '</a>'; $adminLink .= '<a class="btn btn-default" href="#" onclick="top.loadEditId(' . $row['uid'] . ');top.goToModule(\'web_list\'); return false;">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render() . '</a>'; // "View page" icon is added: $adminLink .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($row['uid'], '', BackendUtility::BEgetRootLine($row['uid']))) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a>'; } else { if ($row['pid'] == -1) { $getVars = '&ADMCMD_vPrev[' . rawurlencode($table . ':' . $row['t3ver_oid']) . ']=' . $row['uid']; // "View page" icon is added: $adminLink .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($row['_REAL_PID'], '', BackendUtility::BEgetRootLine($row['_REAL_PID']), '', '', $getVars)) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a>'; } } return '<div class="btn-group btn-group-sm" role="group">' . $adminLink . '</div>'; }
/** * Creates the localization panel * * @param string $table The table * @param mixed[] $row The record for which to make the localization panel. * @return string[] Array with key 0/1 with content for column 1 and 2 */ public function makeLocalizationPanel($table, $row) { $out = array(0 => '', 1 => ''); // Reset translations $this->translations = array(); // Language title and icon: $out[0] = $this->languageFlag($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); // Guard clause so we can quickly return if a record is localized to "all languages" // It should only be possible to localize a record off default (uid 0) // Reasoning: The Parent is for ALL languages... why overlay with a localization? if ((int) $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === -1) { return $out; } $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList); if (is_array($translations)) { $this->translations = $translations['translations']; // Traverse page translations and add icon for each language that does NOT yet exist: $lNew = ''; foreach ($this->pageOverlays as $lUid_OnPage => $lsysRec) { if ($this->isEditable($table) && !isset($translations['translations'][$lUid_OnPage]) && $this->getBackendUserAuthentication()->checkLanguageAccess($lUid_OnPage)) { $url = $this->listURL(); $href = BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $row['uid'] . '][localize]=' . $lUid_OnPage, $url . '&justLocalized=' . rawurlencode($table . ':' . $row['uid'] . ':' . $lUid_OnPage)); $language = BackendUtility::getRecord('sys_language', $lUid_OnPage, 'title'); if ($this->languageIconTitles[$lUid_OnPage]['flagIcon']) { $lC = $this->iconFactory->getIcon($this->languageIconTitles[$lUid_OnPage]['flagIcon'], Icon::SIZE_SMALL)->render(); } else { $lC = $this->languageIconTitles[$lUid_OnPage]['title']; } $lC = '<a href="' . htmlspecialchars($href) . '" title="' . htmlspecialchars($language['title']) . '" class="btn btn-default">' . $lC . '</a> '; $lNew .= $lC; } } if ($lNew) { $out[1] .= $lNew; } } elseif ($row['l18n_parent']) { $out[0] = ' ' . $out[0]; } return $out; }
/** * This returns tablerows for the files in the array $items['sorting']. * * @param File[] $files File items * @return string HTML table rows. */ public function formatFileList(array $files) { $out = ''; // first two keys are "0" (default) and "-1" (multiple), after that comes the "other languages" $allSystemLanguages = GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages(); $systemLanguages = array_filter($allSystemLanguages, function ($languageRecord) { if ($languageRecord['uid'] === -1 || $languageRecord['uid'] === 0 || !$this->getBackendUser()->checkLanguageAccess($languageRecord['uid'])) { return false; } else { return true; } }); foreach ($files as $fileObject) { // Initialization $this->counter++; $this->totalbytes += $fileObject->getSize(); $ext = $fileObject->getExtension(); $fileName = trim($fileObject->getName()); // The icon with link $theIcon = '<span title="' . htmlspecialchars($fileName . ' [' . (int) $fileObject->getUid() . ']') . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>'; if ($this->clickMenus) { $theIcon = BackendUtility::wrapClickMenuOnIcon($theIcon, $fileObject->getCombinedIdentifier()); } // Preparing and getting the data-array $theData = array(); foreach ($this->fieldArray as $field) { switch ($field) { case 'size': $theData[$field] = GeneralUtility::formatSize($fileObject->getSize(), $this->getLanguageService()->getLL('byteSizeUnits', true)); break; case 'rw': $theData[$field] = '' . (!$fileObject->checkActionPermission('read') ? ' ' : '<strong class="text-danger">' . $this->getLanguageService()->getLL('read', true) . '</strong>') . (!$fileObject->checkActionPermission('write') ? '' : '<strong class="text-danger">' . $this->getLanguageService()->getLL('write', true) . '</strong>'); break; case 'fileext': $theData[$field] = strtoupper($ext); break; case 'tstamp': $theData[$field] = BackendUtility::date($fileObject->getModificationTime()); break; case '_CONTROL_': $theData[$field] = $this->makeEdit($fileObject); break; case '_CLIPBOARD_': $theData[$field] = $this->makeClip($fileObject); break; case '_LOCALIZATION_': if (!empty($systemLanguages) && $fileObject->isIndexed() && $fileObject->checkActionPermission('write') && $this->getBackendUser()->check('tables_modify', 'sys_file_metadata')) { $metaDataRecord = $fileObject->_getMetaData(); $translations = $this->getTranslationsForMetaData($metaDataRecord); $languageCode = ''; foreach ($systemLanguages as $language) { $languageId = $language['uid']; $flagIcon = $language['flagIcon']; if (array_key_exists($languageId, $translations)) { $title = htmlspecialchars(sprintf($this->getLanguageService()->getLL('editMetadataForLanguage'), $language['title'])); // @todo the overlay for the flag needs to be added ($flagIcon . '-overlay') $urlParameters = ['edit' => ['sys_file_metadata' => [$translations[$languageId]['uid'] => 'edit']], 'returnUrl' => $this->listURL()]; $flagButtonIcon = $this->iconFactory->getIcon($flagIcon, Icon::SIZE_SMALL, 'overlay-edit')->render(); $url = BackendUtility::getModuleUrl('record_edit', $urlParameters); $languageCode .= '<a href="' . htmlspecialchars($url) . '" class="btn btn-default" title="' . $title . '">' . $flagButtonIcon . '</a>'; } else { $parameters = ['justLocalized' => 'sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId, 'returnUrl' => $this->listURL()]; $returnUrl = BackendUtility::getModuleUrl('record_edit', $parameters); $href = BackendUtility::getLinkToDataHandlerAction('&cmd[sys_file_metadata][' . $metaDataRecord['uid'] . '][localize]=' . $languageId, $returnUrl); $flagButtonIcon = '<span title="' . htmlspecialchars(sprintf($this->getLanguageService()->getLL('createMetadataForLanguage'), $language['title'])) . '">' . $this->iconFactory->getIcon($flagIcon, Icon::SIZE_SMALL, 'overlay-new')->render() . '</span>'; $languageCode .= '<a href="' . htmlspecialchars($href) . '" class="btn btn-default">' . $flagButtonIcon . '</a> '; } } // Hide flag button bar when not translated yet $theData[$field] = ' <div class="localisationData btn-group" data-fileid="' . $fileObject->getUid() . '"' . (empty($translations) ? ' style="display: none;"' : '') . '>' . $languageCode . '</div>'; $theData[$field] .= '<a class="btn btn-default filelist-translationToggler" data-fileid="' . $fileObject->getUid() . '">' . '<span title="' . $this->getLanguageService()->getLL('translateMetadata', true) . '">' . $this->iconFactory->getIcon('mimetypes-x-content-page-language-overlay', Icon::SIZE_SMALL)->render() . '</span>' . '</a>'; } break; case '_REF_': $theData[$field] = $this->makeRef($fileObject); break; case 'file': // Edit metadata of file $theData[$field] = $this->linkWrapFile(htmlspecialchars($fileName), $fileObject); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $theData[$field] .= $flashMessage->render(); // Thumbnails? } elseif ($this->thumbs && ($this->isImage($ext) || $this->isMediaFile($ext))) { $processedFile = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array()); if ($processedFile) { $thumbUrl = $processedFile->getPublicUrl(true); $theData[$field] .= '<br /><img src="' . $thumbUrl . '" ' . 'width="' . $processedFile->getProperty('width') . '" ' . 'height="' . $processedFile->getProperty('height') . '" ' . 'title="' . htmlspecialchars($fileName) . '" alt="" />'; } } break; default: $theData[$field] = ''; if ($fileObject->hasProperty($field)) { $theData[$field] = htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getProperty($field), $this->fixedL)); } } } $out .= $this->addelement(1, $theIcon, $theData); } return $out; }
/** * Returns a URL with a command to TYPO3 Core Engine (tce_db.php) * See description of the API elsewhere. * * @param string $params is a set of GET params to send to tce_db.php. Example: "&cmd[tt_content][123][move]=456" or "&data[tt_content][123][hidden]=1&data[tt_content][123][title]=Hello%20World * @param string|int $redirectUrl Redirect URL, default is to use GeneralUtility::getIndpEnv('REQUEST_URI'), -1 means to generate an URL for JavaScript using T3_THIS_LOCATION * @return string URL to BackendUtility::getModuleUrl('tce_db') + parameters * @see \TYPO3\CMS\Backend\Utility\BackendUtility::editOnClick() * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use BackendUtility::getLinkToDataHandlerAction() instead */ public function issueCommand($params, $redirectUrl = '') { GeneralUtility::logDeprecatedFunction(); return BackendUtility::getLinkToDataHandlerAction($params, $redirectUrl); }
/** * Make selector box for creating new translation for a record or switching to edit the record in an existing * language. * Displays only languages which are available for the current page. * * @param string $table Table name * @param int $uid Uid for which to create a new language * @param int $pid Pid of the record */ public function languageSwitch($table, $uid, $pid = null) { $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField']; $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; // Table editable and activated for languages? if ($this->getBackendUser()->check('tables_modify', $table) && $languageField && $transOrigPointerField && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) { if (is_null($pid)) { $row = BackendUtility::getRecord($table, $uid, 'pid'); $pid = $row['pid']; } // Get all available languages for the page $langRows = $this->getLanguages($pid); // Page available in other languages than default language? if (is_array($langRows) && count($langRows) > 1) { $rowsByLang = array(); $fetchFields = 'uid,' . $languageField . ',' . $transOrigPointerField; // Get record in current language $rowCurrent = BackendUtility::getLiveVersionOfRecord($table, $uid, $fetchFields); if (!is_array($rowCurrent)) { $rowCurrent = BackendUtility::getRecord($table, $uid, $fetchFields); } $currentLanguage = (int) $rowCurrent[$languageField]; // Disabled for records with [all] language! if ($currentLanguage > -1) { // Get record in default language if needed if ($currentLanguage && $rowCurrent[$transOrigPointerField]) { $rowsByLang[0] = BackendUtility::getLiveVersionOfRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields); if (!is_array($rowsByLang[0])) { $rowsByLang[0] = BackendUtility::getRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields); } } else { $rowsByLang[$rowCurrent[$languageField]] = $rowCurrent; } if ($rowCurrent[$transOrigPointerField] || $currentLanguage === 0) { // Get record in other languages to see what's already available $translations = $this->getDatabaseConnection()->exec_SELECTgetRows($fetchFields, $table, 'pid=' . (int) $pid . ' AND ' . $languageField . '>0' . ' AND ' . $transOrigPointerField . '=' . (int) $rowsByLang[0]['uid'] . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table)); foreach ($translations as $row) { $rowsByLang[$row[$languageField]] = $row; } } $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $languageMenu->setIdentifier('_langSelector'); $languageMenu->setLabel($this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.language', true)); foreach ($langRows as $lang) { if ($this->getBackendUser()->checkLanguageAccess($lang['uid'])) { $newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' [' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.new', true) . ']'; // Create url for creating a localized record if ($newTranslation) { $redirectUrl = BackendUtility::getModuleUrl('record_edit', array('justLocalized' => $table . ':' . $rowsByLang[0]['uid'] . ':' . $lang['uid'], 'returnUrl' => $this->retUrl)); $href = BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $rowsByLang[0]['uid'] . '][localize]=' . $lang['uid'], $redirectUrl); } else { $href = BackendUtility::getModuleUrl('record_edit', array('edit[' . $table . '][' . $rowsByLang[$lang['uid']]['uid'] . ']' => 'edit', 'returnUrl' => $this->retUrl)); } $menuItem = $languageMenu->makeMenuItem()->setTitle($lang['title'] . $newTranslation)->setHref($href); if ((int) $lang['uid'] === $currentLanguage) { $menuItem->setActive(true); } $languageMenu->addMenuItem($menuItem); } } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($languageMenu); } } } }
/** * Creates the localization panel * * @param string $table The table * @param mixed[] $row The record for which to make the localization panel. * * @return string[] Array with key 0/1 with content for column 1 and 2 */ public function makeLocalizationPanel($table, $row) { $out = array(0 => '', 1 => ''); // Reset translations $this->translations = array(); // Language title and icon: $out[0] = $this->languageFlag($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList); if (is_array($translations)) { $this->translations = $translations['translations']; // Traverse page translations and add icon for each language that does NOT yet exist: $lNew = ''; foreach ($this->pageOverlays as $lUid_OnPage => $lsysRec) { if ($this->isEditable($table) && !isset($translations['translations'][$lUid_OnPage]) && $this->getBackendUserAuthentication()->checkLanguageAccess($lUid_OnPage)) { $url = $this->listURL(); $href = BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $row['uid'] . '][localize]=' . $lUid_OnPage, $url . '&justLocalized=' . rawurlencode($table . ':' . $row['uid'] . ':' . $lUid_OnPage)); $language = BackendUtility::getRecord('sys_language', $lUid_OnPage, 'title'); if ($this->languageIconTitles[$lUid_OnPage]['flagIcon']) { $lC = $this->iconFactory->getIcon($this->languageIconTitles[$lUid_OnPage]['flagIcon'], Icon::SIZE_SMALL)->render(); } else { $lC = $this->languageIconTitles[$lUid_OnPage]['title']; } $lC = '<a href="' . htmlspecialchars($href) . '" title="' . htmlspecialchars($language['title']) . '">' . $lC . '</a> '; $lNew .= $lC; } } if ($lNew) { $out[1] .= $lNew; } } elseif ($row['l18n_parent']) { $out[0] = '<span style="padding-left: 40px;">' . $out[0] . '</span>'; } return $out; }
/** * Creates the version selector for the page id inputted. * Moved out of the core file \TYPO3\CMS\Backend\Template\DocumentTemplate * * @param int $id Page id to create selector for. * @param bool $noAction If set, there will be no button for swapping page. * @return string * @see \TYPO3\CMS\Backend\Template\DocumentTemplate */ public function getVersionSelector($id, $noAction = false) { if ($id <= 0) { return ''; } if ($GLOBALS['BE_USER']->workspace == 0) { $lang = $this->getLanguageService(); // Get Current page record: $curPage = BackendUtility::getRecord('pages', $id); // If the selected page is not online, find the right ID $onlineId = $curPage['pid'] == -1 ? $curPage['t3ver_oid'] : $id; // Select all versions of online version: $versions = BackendUtility::selectVersionsOfRecord('pages', $onlineId, 'uid,pid,t3ver_label,t3ver_oid,t3ver_wsid,t3ver_id', null); // If more than one was found...: if (count($versions) > 1) { // Create selector box entries: $opt = []; foreach ($versions as $vRow) { if ($vRow['uid'] == $onlineId) { // Live version $label = '[' . htmlspecialchars($lang->sL('LLL:EXT:version/Resources/Private/Language/locallang.xlf:versionSelect.live')) . ']'; } else { $label = $vRow['t3ver_label'] . ' (' . htmlspecialchars($lang->sL('LLL:EXT:version/Resources/Private/Language/locallang.xlf:versionId')) . ' ' . $vRow['t3ver_id'] . ($vRow['t3ver_wsid'] != 0 ? ' ' . htmlspecialchars($lang->sL('LLL:EXT:version/Resources/Private/Language/locallang.xlf:workspaceId')) . ' ' . $vRow['t3ver_wsid'] : '') . ')'; } $opt[] = '<option value="' . htmlspecialchars(GeneralUtility::linkThisScript(['id' => $vRow['uid']])) . '"' . ($id == $vRow['uid'] ? ' selected="selected"' : '') . '>' . htmlspecialchars($label) . '</option>'; } /** @var $iconFactory \TYPO3\CMS\Core\Imaging\IconFactory */ $iconFactory = GeneralUtility::makeInstance(IconFactory::class); // Add management link: $management = ' <a class="btn btn-default" href="' . htmlspecialchars(\TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('web_txversionM1', ['table' => 'pages', 'uid' => $onlineId])) . '"> ' . $iconFactory->getIcon('actions-version-page-open', Icon::SIZE_SMALL)->render() . ' ' . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:ver.mgm')) . ' </a>'; // Create onchange handler: $onChange = 'window.location.href=this.options[this.selectedIndex].value;'; // Controls: if ($id == $onlineId) { $controls = '<strong class="text-success">' . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:ver.online')) . '</strong>'; } elseif (!$noAction) { $href = BackendUtility::getLinkToDataHandlerAction('&cmd[pages][' . $onlineId . '][version][swapWith]=' . $id . '&cmd[pages][' . $onlineId . '][version][action]=swap', GeneralUtility::linkThisScript(['id' => $onlineId])); $controls = ' <a href="' . htmlspecialchars($href) . '" class="btn btn-default" title="' . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:ver.swapPage')) . '"> ' . $iconFactory->getIcon('actions-version-swap-version', Icon::SIZE_SMALL)->render() . ' ' . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:ver.swap')) . ' </a>'; } // Write out HTML code: return ' <!-- Version selector: --> <div id="typo3-version-selector" class="form-inline form-inline-spaced"> <div class="form-group"> <label for="version-selector">' . htmlspecialchars($lang->sL('LLL:EXT:version/Resources/Private/Language/locallang.xlf:versionSelect.label')) . '</label> <select id="version-selector" class="form-control" onchange="' . htmlspecialchars($onChange) . '"> ' . implode('', $opt) . ' </select> </div> <div class="form-group"> ' . $controls . ' </div> <div class="form-group"> ' . $management . ' </div> </div> '; } } }
/** * Make selector box for creating new translation for a record or switching to edit the record in an existing * language. * Displays only languages which are available for the current page. * * @param string $table Table name * @param int $uid Uid for which to create a new language * @param int $pid Pid of the record */ public function languageSwitch($table, $uid, $pid = null) { $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField']; $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; // Table editable and activated for languages? if ($this->getBackendUser()->check('tables_modify', $table) && $languageField && $transOrigPointerField && $table !== 'pages_language_overlay') { if (is_null($pid)) { $row = BackendUtility::getRecord($table, $uid, 'pid'); $pid = $row['pid']; } // Get all available languages for the page $langRows = $this->getLanguages($pid); // Page available in other languages than default language? if (is_array($langRows) && count($langRows) > 1) { $rowsByLang = []; $fetchFields = 'uid,' . $languageField . ',' . $transOrigPointerField; // Get record in current language $rowCurrent = BackendUtility::getLiveVersionOfRecord($table, $uid, $fetchFields); if (!is_array($rowCurrent)) { $rowCurrent = BackendUtility::getRecord($table, $uid, $fetchFields); } $currentLanguage = (int) $rowCurrent[$languageField]; // Disabled for records with [all] language! if ($currentLanguage > -1) { // Get record in default language if needed if ($currentLanguage && $rowCurrent[$transOrigPointerField]) { $rowsByLang[0] = BackendUtility::getLiveVersionOfRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields); if (!is_array($rowsByLang[0])) { $rowsByLang[0] = BackendUtility::getRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields); } } else { $rowsByLang[$rowCurrent[$languageField]] = $rowCurrent; } if ($rowCurrent[$transOrigPointerField] || $currentLanguage === 0) { // Get record in other languages to see what's already available $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class))->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder->select(...GeneralUtility::trimExplode(',', $fetchFields, true))->from($table)->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)), $queryBuilder->expr()->gt($languageField, $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), $queryBuilder->expr()->eq($transOrigPointerField, $queryBuilder->createNamedParameter($rowsByLang[0]['uid'], \PDO::PARAM_INT)))->execute(); while ($row = $result->fetch()) { $rowsByLang[$row[$languageField]] = $row; } } $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $languageMenu->setIdentifier('_langSelector'); $languageMenu->setLabel(htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.language'))); foreach ($langRows as $lang) { if ($this->getBackendUser()->checkLanguageAccess($lang['uid'])) { $newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' [' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.new')) . ']'; // Create url for creating a localized record $addOption = true; if ($newTranslation) { $redirectUrl = BackendUtility::getModuleUrl('record_edit', ['justLocalized' => $table . ':' . $rowsByLang[0]['uid'] . ':' . $lang['uid'], 'returnUrl' => $this->retUrl]); if ($currentLanguage === 0) { $href = BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $rowsByLang[0]['uid'] . '][localize]=' . $lang['uid'], $redirectUrl); } else { $addOption = false; } } else { $href = BackendUtility::getModuleUrl('record_edit', ['edit[' . $table . '][' . $rowsByLang[$lang['uid']]['uid'] . ']' => 'edit', 'returnUrl' => $this->retUrl]); } if ($addOption) { $menuItem = $languageMenu->makeMenuItem()->setTitle($lang['title'] . $newTranslation)->setHref($href); if ((int) $lang['uid'] === $currentLanguage) { $menuItem->setActive(true); } $languageMenu->addMenuItem($menuItem); } } } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($languageMenu); } } } }
/** * @param $params * @return string */ protected function getLinkToDataHandlerAction($params) { if (\TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) > 7000000) { return \TYPO3\CMS\Backend\Utility\BackendUtility::getLinkToDataHandlerAction($params); } else { return $this->getPageLayoutController()->doc->issueCommand($params); } }