/** * Wrapping icon in browse tree * * @param string $icon IMG code * @param array $row Data row for element. * * @return string Page icon */ public function wrapIcon($icon, array &$row) { $language = $this->getLanguageService(); // If the record is locked, present a warning sign. if ($lockInfo = \TYPO3\CMS\Backend\Utility\BackendUtility::isRecordLocked('pages', $row['uid'])) { $aOnClick = 'alert(' . $language->JScharCode($lockInfo['msg']) . ');return false;'; $lockIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-warning-in-use', array('title' => htmlspecialchars($lockInfo['msg']))) . '</a>'; } else { $lockIcon = ''; } // Add title attribute to input icon tag $thePageIcon = $this->addTagAttributes($icon, $this->titleAttrib . '="' . $this->getTitleAttrib($row) . '"'); // Wrap icon in click-menu link. if (!$this->ext_IconMode) { /** * Template * * @var \TYPO3\CMS\Backend\Template\DocumentTemplate $tbeTemplate */ $tbeTemplate = $GLOBALS['TBE_TEMPLATE']; $thePageIcon = $tbeTemplate->wrapClickMenuOnIcon($thePageIcon, 'pages', $row['uid'], 0, '&bank=' . $this->bank); } elseif (!strcmp($this->ext_IconMode, 'titlelink')) { $aOnClick = 'return jumpTo(\'' . $this->getJumpToParam($row) . '\',this,\'' . $this->treeName . '\');'; $thePageIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $thePageIcon . '</a>'; } // Add Page ID: if ($this->ext_showPageId) { $pageIdStr = '[' . $row['uid'] . '] '; } else { $pageIdStr = ''; } return $thePageIcon . $lockIcon . $pageIdStr; }
/** * Wrapping icon in browse tree * * @param string $thePageIcon Icon IMG code * @param array $row Data row for element. * @return string Page icon */ public function wrapIcon($thePageIcon, &$row) { // If the record is locked, present a warning sign. if ($lockInfo = \TYPO3\CMS\Backend\Utility\BackendUtility::isRecordLocked('pages', $row['uid'])) { $aOnClick = 'alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;'; $lockIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . IconUtility::getSpriteIcon('status-warning-in-use', array('title' => $lockInfo['msg'])) . '</a>'; } else { $lockIcon = ''; } // Wrap icon in click-menu link. if (!$this->ext_IconMode) { $thePageIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($thePageIcon, 'pages', $row['uid'], 0, '&bank=' . $this->bank); } elseif ($this->ext_IconMode === 'titlelink') { $aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->getJumpToParam($row)) . ',this,' . GeneralUtility::quoteJSvalue($this->treeName) . ');'; $thePageIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $thePageIcon . '</a>'; } // Wrap icon in a drag/drop span. $dragDropIcon = '<span class="dragIcon" id="dragIconID_' . $row['uid'] . '">' . $thePageIcon . '</span>'; // Add Page ID: $pageIdStr = ''; if ($this->ext_showPageId) { $pageIdStr = '<span class="dragId">[' . $row['uid'] . ']</span> '; } // Call stats information hook $stat = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { $_params = array('pages', $row['uid']); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } return $dragDropIcon . $lockIcon . $pageIdStr . $stat; }
/** * 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: $params = '&edit[tt_content][' . $this->tt_contentData['nextThree'][$row['uid']] . ']=edit'; $out .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, '', GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid'])) . '" 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>'; } } } } $additionalIcons = array(); $additionalIcons[] = $this->getIcon('tt_content', $row) . ' '; $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 ' . ($this->isDragAndDropAllowed($row) ? '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">'; }
/** * Creates a node with the given record information * * @param array $record * @param int $mountPoint * @return \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode */ public static function getNewNode($record, $mountPoint = 0) { if (self::$titleLength === NULL) { self::$useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle'); self::$addIdAsPrefix = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPageIdWithTitle'); self::$addDomainName = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showDomainNameWithTitle'); self::$backgroundColors = $GLOBALS['BE_USER']->getTSConfigProp('options.pageTree.backgroundColor'); self::$titleLength = (int) $GLOBALS['BE_USER']->uc['titleLen']; } /** @var $subNode \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode */ $subNode = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode::class); $subNode->setRecord($record); $subNode->setCls($record['_CSSCLASS']); $subNode->setType('pages'); $subNode->setId($record['uid']); $subNode->setMountPoint($mountPoint); $subNode->setWorkspaceId($record['_ORIG_uid'] ?: $record['uid']); $subNode->setBackgroundColor(self::$backgroundColors[$record['uid']]); $field = 'title'; $text = $record['title']; if (self::$useNavTitle && trim($record['nav_title']) !== '') { $field = 'nav_title'; $text = $record['nav_title']; } if (trim($text) === '') { $visibleText = '[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title', TRUE) . ']'; } else { $visibleText = $text; } $visibleText = GeneralUtility::fixed_lgd_cs($visibleText, self::$titleLength); $suffix = ''; if (self::$addDomainName) { $domain = self::getDomainName($record['uid']); $suffix = $domain !== '' ? ' [' . $domain . ']' : ''; } $qtip = str_replace(' - ', '<br />', htmlspecialchars(BackendUtility::titleAttribForPages($record, '', FALSE))); $prefix = ''; $lockInfo = BackendUtility::isRecordLocked('pages', $record['uid']); if (is_array($lockInfo)) { $qtip .= '<br />' . htmlspecialchars($lockInfo['msg']); $prefix .= IconUtility::getSpriteIcon('status-warning-in-use', array('class' => 'typo3-pagetree-status')); } // Call stats information hook $stat = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { $_params = array('pages', $record['uid']); $fakeThis = NULL; foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $fakeThis); } } $prefix .= htmlspecialchars(self::$addIdAsPrefix ? '[' . $record['uid'] . '] ' : ''); $subNode->setEditableText($text); $subNode->setText(htmlspecialchars($visibleText), $field, $prefix, htmlspecialchars($suffix) . $stat); $subNode->setQTip($qtip); if ((int) $record['uid'] !== 0) { $spriteIconCode = IconUtility::getSpriteIconForRecord('pages', $record); } else { $spriteIconCode = IconUtility::getSpriteIcon('apps-pagetree-root'); } $subNode->setSpriteIconCode($spriteIconCode); if (!$subNode->canCreateNewPages() || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $subNode->setIsDropTarget(FALSE); } if (!$subNode->canBeEdited() || !$subNode->canBeRemoved() || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $subNode->setDraggable(FALSE); } return $subNode; }
/** * Render the control-icons for a record header (create new, sorting, delete, disable/enable). * Most of the parts are copy&paste from TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList and * modified for the JavaScript calls here * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The table (foreign_table) we create control-icons for * @param array $rec The current record of that foreign_table * @param array $config (modified) TCA configuration of the field * @return string The HTML code with the control-icons * @todo Define visibility */ public function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array(), $isVirtualRecord = FALSE) { // Initialize: $cells = array(); $isNewItem = substr($rec['uid'], 0, 3) == 'NEW'; $isParentExisting = MathUtility::canBeInterpretedAsInteger($parentUid); $tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl']; $tcaTableCols =& $GLOBALS['TCA'][$foreign_table]['columns']; $isPagesTable = $foreign_table == 'pages' ? TRUE : FALSE; $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || !$isOnSymmetricSide && $config['foreign_sortby'] || $isOnSymmetricSide && $config['symmetric_sortby'] ? TRUE : FALSE; $nameObject = $this->inlineNames['object']; $nameObjectFt = $nameObject . self::Structure_Separator . $foreign_table; $nameObjectFtId = $nameObjectFt . self::Structure_Separator . $rec['uid']; $calcPerms = $GLOBALS['BE_USER']->calcPerms(BackendUtility::readPageAccess($rec['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1))); // If the listed table is 'pages' we have to request the permission settings for each page: if ($isPagesTable) { $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(BackendUtility::getRecord('pages', $rec['uid'])); } // This expresses the edit permissions for this particular element: $permsEdit = $isPagesTable && $localCalcPerms & 2 || !$isPagesTable && $calcPerms & 16; // Controls: Defines which controls should be shown $enabledControls = $config['appearance']['enabledControls']; // Hook: Can disable/enable single controls for specific child records: foreach ($this->hookObjects as $hookObj) { $hookObj->renderForeignRecordHeaderControl_preProcess($parentUid, $foreign_table, $rec, $config, $isVirtualRecord, $enabledControls); } // Icon to visualize that a required field is nested in this inline level: $cells['required'] = '<img name="' . $nameObjectFtId . '_req" src="clear.gif" width="10" height="10" hspace="4" vspace="3" alt="" />'; if (isset($rec['__create'])) { $cells['localize.isLocalizable'] = IconUtility::getSpriteIcon('actions-edit-localize-status-low', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:localize.isLocalizable', TRUE))); } elseif (isset($rec['__remove'])) { $cells['localize.wasRemovedInOriginal'] = IconUtility::getSpriteIcon('actions-edit-localize-status-high', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:localize.wasRemovedInOriginal', TRUE))); } // "Info": (All records) if ($enabledControls['info'] && !$isNewItem) { if ($rec['table_local'] === 'sys_file') { $uid = (int) substr($rec['uid_local'], 9); $table = '_FILE'; } else { $uid = $rec['uid']; $table = $foreign_table; } $cells['info'] = '<a href="#" onclick="' . htmlspecialchars('top.launchView(\'' . $table . '\', \'' . $uid . '\'); return false;') . '">' . IconUtility::getSpriteIcon('status-dialog-information', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:showInfo', TRUE))) . '</a>'; } // If the table is NOT a read-only table, then show these links: if (!$tcaTableCtrl['readOnly'] && !$isVirtualRecord) { // "New record after" link (ONLY if the records in the table are sorted by a "sortby"-row or if default values can depend on previous record): if ($enabledControls['new'] && ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues'])) { if (!$isPagesTable && $calcPerms & 16 || $isPagesTable && $calcPerms & 8) { $onClick = 'return inline.createNewRecord(\'' . $nameObjectFt . '\',\'' . $rec['uid'] . '\')'; $class = ' class="inlineNewButton ' . $this->inlineData['config'][$nameObject]['md5'] . '"'; if ($config['inline']['inlineNewButtonStyle']) { $style = ' style="' . $config['inline']['inlineNewButtonStyle'] . '"'; } $cells['new'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '"' . $class . $style . '>' . IconUtility::getSpriteIcon('actions-' . ($isPagesTable ? 'page' : 'document') . '-new', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:new' . ($isPagesTable ? 'Page' : 'Record'), TRUE))) . '</a>'; } } // "Up/Down" links if ($enabledControls['sort'] && $permsEdit && $enableManualSorting) { $onClick = 'return inline.changeSorting(\'' . $nameObjectFtId . '\', \'1\')'; // Up $style = $config['inline']['first'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; $cells['sort.up'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" class="sortingUp" ' . $style . '>' . IconUtility::getSpriteIcon('actions-move-up', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:moveUp', TRUE))) . '</a>'; $onClick = 'return inline.changeSorting(\'' . $nameObjectFtId . '\', \'-1\')'; // Down $style = $config['inline']['last'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; $cells['sort.down'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" class="sortingDown" ' . $style . '>' . IconUtility::getSpriteIcon('actions-move-down', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:moveDown', TRUE))) . '</a>'; } // "Delete" link: if ($enabledControls['delete'] && ($isPagesTable && $localCalcPerms & 4 || !$isPagesTable && $calcPerms & 16)) { $onClick = 'inline.deleteRecord(\'' . $nameObjectFtId . '\');'; $cells['delete'] = '<a href="#" onclick="' . htmlspecialchars('if (confirm(' . GeneralUtility::quoteJSvalue($GLOBALS['LANG']->getLL('deleteWarning')) . ')) { ' . $onClick . ' } return false;') . '">' . IconUtility::getSpriteIcon('actions-edit-delete', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:delete', TRUE))) . '</a>'; } // "Hide/Unhide" links: $hiddenField = $tcaTableCtrl['enablecolumns']['disabled']; if ($enabledControls['hide'] && $permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $foreign_table . ':' . $hiddenField))) { $onClick = 'return inline.enableDisableRecord(\'' . $nameObjectFtId . '\')'; if ($rec[$hiddenField]) { $cells['hide.unhide'] = '<a href="#" class="hiddenHandle" onclick="' . htmlspecialchars($onClick) . '">' . IconUtility::getSpriteIcon('actions-edit-unhide', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:unHide' . ($isPagesTable ? 'Page' : ''), TRUE), 'id' => $nameObjectFtId . '_disabled')) . '</a>'; } else { $cells['hide.hide'] = '<a href="#" class="hiddenHandle" onclick="' . htmlspecialchars($onClick) . '">' . IconUtility::getSpriteIcon('actions-edit-hide', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:hide' . ($isPagesTable ? 'Page' : ''), TRUE), 'id' => $nameObjectFtId . '_disabled')) . '</a>'; } } // Drag&Drop Sorting: Sortable handler for script.aculo.us if ($enabledControls['dragdrop'] && $permsEdit && $enableManualSorting && $config['appearance']['useSortable']) { $cells['dragdrop'] = IconUtility::getSpriteIcon('actions-move-move', array('data-id' => $rec['uid'], 'class' => 'sortableHandle', 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.move', TRUE))); } } elseif ($isVirtualRecord && $isParentExisting) { if ($enabledControls['localize'] && isset($rec['__create'])) { $onClick = 'inline.synchronizeLocalizeRecords(\'' . $nameObjectFt . '\', ' . $rec['uid'] . ');'; $cells['localize'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . IconUtility::getSpriteIcon('actions-document-localize', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:localize', TRUE))) . '</a>'; } } // If the record is edit-locked by another user, we will show a little warning sign: if ($lockInfo = BackendUtility::isRecordLocked($foreign_table, $rec['uid'])) { $cells['locked'] = '<a href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;">' . IconUtility::getSpriteIcon('status-warning-in-use', array('title' => $lockInfo['msg'])) . '</a>'; } // Hook: Post-processing of single controls for specific child records: foreach ($this->hookObjects as $hookObj) { $hookObj->renderForeignRecordHeaderControl_postProcess($parentUid, $foreign_table, $rec, $config, $isVirtualRecord, $cells); } return '<!-- CONTROL PANEL: ' . $foreign_table . ':' . $rec['uid'] . ' -->' . implode('', $cells); }
/** * Rendering a single row for the list * * @param string $table Table name * @param mixed[] $row Current record * @param int $cc Counter, counting for each time an element is rendered (used for alternating colors) * @param string $titleCol Table field (column) where header value is found * @param string $thumbsCol Table field (column) where (possible) thumbnails can be found * @param int $indent Indent from left. * @return string Table row for the element * @access private * @see getTable() */ public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0) { if (!is_array($row)) { return ''; } $rowOutput = ''; $id_orig = null; // If in search mode, make sure the preview will show the correct page if ((string) $this->searchString !== '') { $id_orig = $this->id; $this->id = $row['pid']; } // Add special classes for first and last row $rowSpecial = ''; if ($cc == 1 && $indent == 0) { $rowSpecial .= ' firstcol'; } if ($cc == $this->totalRowCount || $cc == $this->iLimit) { $rowSpecial .= ' lastcol'; } $row_bgColor = ' class="' . $rowSpecial . '"'; // Overriding with versions background color if any: $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor; // Incr. counter. $this->counter++; // The icon with link $toolTip = BackendUtility::getRecordToolTip($row, $table); $additionalStyle = $indent ? ' style="margin-left: ' . $indent . 'px;"' : ''; $iconImg = '<span ' . $toolTip . ' ' . $additionalStyle . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>'; $theIcon = $this->clickMenuEnabled ? BackendUtility::wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg; // Preparing and getting the data-array $theData = array(); $localizationMarkerClass = ''; foreach ($this->fieldArray as $fCol) { if ($fCol == $titleCol) { $recTitle = BackendUtility::getRecordTitle($table, $row, false, true); $warning = ''; // If the record is edit-locked by another user, we will show a little warning sign: $lockInfo = BackendUtility::isRecordLocked($table, $row['uid']); if ($lockInfo) { $warning = '<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>'; } $theData[$fCol] = $theData['__label'] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row); // Render thumbnails, if: // - a thumbnail column exists // - there is content in it // - the thumbnail column is visible for the current type $type = 0; if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) { $typeColumn = $GLOBALS['TCA'][$table]['ctrl']['type']; $type = $row[$typeColumn]; } // If current type doesn't exist, set it to 0 (or to 1 for historical reasons, // if 0 doesn't exist) if (!isset($GLOBALS['TCA'][$table]['types'][$type])) { $type = isset($GLOBALS['TCA'][$table]['types'][0]) ? 0 : 1; } $visibleColumns = $GLOBALS['TCA'][$table]['types'][$type]['showitem']; if ($this->thumbs && trim($row[$thumbsCol]) && preg_match('/(^|(.*(;|,)?))' . $thumbsCol . '(((;|,).*)|$)/', $visibleColumns) === 1) { $theData[$fCol] .= '<br />' . $this->thumbCode($row, $table, $thumbsCol); } if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { // It's a translated record with a language parent $localizationMarkerClass = ' localization'; } } elseif ($fCol == 'pid') { $theData[$fCol] = $row[$fCol]; } elseif ($fCol == '_PATH_') { $theData[$fCol] = $this->recPath($row['pid']); } elseif ($fCol == '_REF_') { $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']); } elseif ($fCol == '_CONTROL_') { $theData[$fCol] = $this->makeControl($table, $row); } elseif ($fCol == '_CLIPBOARD_') { $theData[$fCol] = $this->makeClip($table, $row); } elseif ($fCol == '_LOCALIZATION_') { list($lC1, $lC2) = $this->makeLocalizationPanel($table, $row); $theData[$fCol] = $lC1; $theData[$fCol . 'b'] = '<div class="btn-group">' . $lC2 . '</div>'; } elseif ($fCol == '_LOCALIZATION_b') { // deliberately empty } else { $pageId = $table === 'pages' ? $row['uid'] : $row['pid']; $tmpProc = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid'], true, $pageId); $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); if ($this->csvOutput) { $row[$fCol] = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); } } } // Reset the ID if it was overwritten if ((string) $this->searchString !== '') { $this->id = $id_orig; } // Add row to CSV list: if ($this->csvOutput) { $this->addToCSV($row); } // Add classes to table cells $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass; $this->addElement_tdCssClass['_CONTROL_'] = 'col-control'; if ($this->getModule()->MOD_SETTINGS['clipBoard']) { $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard'; } $this->addElement_tdCssClass['_PATH_'] = 'col-path'; $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa'; $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb'; // Create element in table cells: $theData['uid'] = $row['uid']; if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) { $theData['parent'] = $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; } $rowOutput .= $this->addElement(1, $theIcon, $theData, $row_bgColor); // Finally, return table row element: return $rowOutput; }
/** * Rendering the quick-edit view. * * @return string */ public function renderQuickEdit() { $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $lang = $this->getLanguageService(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND colPos=' . (int) substr($edit_record, 10) . ' AND sys_language_uid=' . (int) $this->current_sys_language . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = BackendUtility::getModuleUrl('record_edit', array('edit[tt_content][' . implode(',', $idListA) . ']' => 'edit', 'returnUrl' => $this->local_linkThisScript(array('edit_record' => '')))); HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $databaseConnection->exec_SELECTquery('*', 'sys_log', 'userid=' . (int) $beUser->user['uid'] . ' AND NEWid=' . $databaseConnection->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $databaseConnection->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } $edit_record = $this->makeQuickEditMenu($edit_record); // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); $tableName = $this->eRParts[0]; // Delete-button flag? $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($tableName !== 'pages' && $this->EDIT_CONTENT || $tableName === 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = false; $undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($tableName, 'sys_history') . ' AND recuid=' . (int) $this->eRParts[1], '', 'tstamp DESC', '1'); if ($this->undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) { $this->undoButton = true; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Creating editing form: if ($edit_record) { // Splitting uid parts for special features, if new: list($uidVal, $neighborRecordUid, $ex_colPos) = explode('/', $this->eRParts[1]); if ($uidVal === 'new') { $command = 'new'; // Page id of this new record $theUid = $this->id; if ($neighborRecordUid) { $theUid = $neighborRecordUid; } } else { $command = 'edit'; $theUid = $uidVal; // Convert $uidVal to workspace version if any: $draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $tableName, $theUid, 'uid'); if ($draftRecord) { $theUid = $draftRecord['uid']; } } // @todo: Hack because DatabaseInitializeNewRow reads from _GP directly $GLOBALS['_GET']['defVals'][$tableName] = array('colPos' => (int) $ex_colPos, 'sys_language_uid' => (int) $this->current_sys_language); /** @var TcaDatabaseRecord $formDataGroup */ $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class); /** @var FormDataCompiler $formDataCompiler */ $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup); /** @var NodeFactory $nodeFactory */ $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); try { $formDataCompilerInput = ['tableName' => $tableName, 'vanillaUid' => (int) $theUid, 'command' => $command]; $formData = $formDataCompiler->compile($formDataCompilerInput); if ($command !== 'new') { BackendUtility::lockRecords($tableName, $formData['databaseRow']['uid'], $tableName === 'tt_content' ? $formData['databaseRow']['pid'] : 0); } $formData['renderType'] = 'outerWrapContainer'; $formResult = $nodeFactory->create($formData)->render(); $panel = $formResult['html']; $formResult['html'] = ''; /** @var FormResultCompiler $formResultCompiler */ $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class); $formResultCompiler->mergeResult($formResult); $row = $formData['databaseRow']; $new_unique_uid = ''; if ($command === 'new') { $new_unique_uid = $row['uid']; } // Add hidden fields: if ($uidVal == 'new') { $panel .= '<input type="hidden" name="data[' . $tableName . '][' . $row['uid'] . '][pid]" value="' . $row['pid'] . '" />'; } $redirect = $uidVal == 'new' ? BackendUtility::getModuleUrl($this->moduleName, ['id' => $this->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl]) : $this->R_URI; $panel .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($redirect) . '" /> '; // Add JavaScript as needed around the form: $content = $formResultCompiler->JStop() . $panel . $formResultCompiler->printNeededJSFunctions(); // Display "is-locked" message: if ($command === 'edit') { $lockInfo = BackendUtility::isRecordLocked($tableName, $formData['databaseRow']['uid']); if ($lockInfo) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } } } catch (AccessDeniedException $e) { // If no edit access, print error message: $content = '<h2>' . $lang->getLL('noAccess', true) . '</h2>'; $content .= '<div>' . $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : '') . '</div>'; } } else { // If no edit access, print error message: $content = '<h2>' . $lang->getLL('noAccess') . '</h2>'; $content .= '<div>' . $lang->getLL('noAccess_msg') . '</div>'; } // Element selection matrix: if ($tableName === 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $content .= '<h2>' . $lang->getLL('CEonThisPage') . '</h2>'; // PositionMap $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class); $posMap->cur_sys_language = $this->current_sys_language; $content .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); // Toggle hidden ContentElements $numberOfHiddenElements = $this->getNumberOfHiddenElements(); if ($numberOfHiddenElements) { $content .= '<div class="checkbox">'; $content .= '<label for="checkTt_content_showHidden">'; $content .= BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"'); $content .= !$numberOfHiddenElements ? '<span class="text-muted">' . $lang->getLL('hiddenCE', true) . '</span>' : $lang->getLL('hiddenCE', true) . ' (' . $numberOfHiddenElements . ')'; $content .= '</label>'; $content .= '</div>'; } // CSH $content .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement'); } return $content; }
/** * Rendering a single row for the list * * @param string $table Table name * @param array $row Current record * @param integer $cc Counter, counting for each time an element is rendered (used for alternating colors) * @param string $titleCol Table field (column) where header value is found * @param string $thumbsCol Table field (column) where (possible) thumbnails can be found * @param integer $indent Indent from left. * @return string Table row for the element * @access private * @see getTable() * @todo Define visibility */ public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0) { $iOut = ''; // If in search mode, make sure the preview will show the correct page if (strlen($this->searchString)) { $id_orig = $this->id; $this->id = $row['pid']; } if (is_array($row)) { // Add special classes for first and last row $rowSpecial = ''; if ($cc == 1 && $indent == 0) { $rowSpecial .= ' firstcol'; } if ($cc == $this->totalRowCount || $cc == $this->iLimit) { $rowSpecial .= ' lastcol'; } // Background color, if any: if ($this->alternateBgColors) { $row_bgColor = $cc % 2 ? ' class="db_list_normal' . $rowSpecial . '"' : ' class="db_list_alt' . $rowSpecial . '"'; } else { $row_bgColor = ' class="db_list_normal' . $rowSpecial . '"'; } // Overriding with versions background color if any: $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor; // Incr. counter. $this->counter++; // The icon with link $alttext = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordIconAltText($row, $table); $iconImg = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $row, array('title' => htmlspecialchars($alttext), 'style' => $indent ? ' margin-left: ' . $indent . 'px;' : '')); $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg; // Preparing and getting the data-array $theData = array(); foreach ($this->fieldArray as $fCol) { if ($fCol == $titleCol) { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $row, FALSE, TRUE); // If the record is edit-locked by another user, we will show a little warning sign: if ($lockInfo = \TYPO3\CMS\Backend\Utility\BackendUtility::isRecordLocked($table, $row['uid'])) { $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '" title="' . htmlspecialchars($lockInfo['msg']) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-warning-in-use') . '</a>'; } $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row); // Render thumbsnails if a thumbnail column exists and there is content in it: if ($this->thumbs && trim($row[$thumbsCol])) { $theData[$fCol] .= '<br />' . $this->thumbCode($row, $table, $thumbsCol); } $localizationMarkerClass = ''; if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { // It's a translated record with a language parent $localizationMarkerClass = ' localization'; } } elseif ($fCol == 'pid') { $theData[$fCol] = $row[$fCol]; } elseif ($fCol == '_PATH_') { $theData[$fCol] = $this->recPath($row['pid']); } elseif ($fCol == '_REF_') { $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']); } elseif ($fCol == '_CONTROL_') { $theData[$fCol] = $this->makeControl($table, $row); } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') { $theData[$fCol] = ' '; } elseif ($fCol == '_CLIPBOARD_') { $theData[$fCol] = $this->makeClip($table, $row); } elseif ($fCol == '_LOCALIZATION_') { list($lC1, $lC2) = $this->makeLocalizationPanel($table, $row); $theData[$fCol] = $lC1; $theData[$fCol . 'b'] = $lC2; } elseif ($fCol == '_LOCALIZATION_b') { } else { $tmpProc = \TYPO3\CMS\Backend\Utility\BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']); $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); if ($this->csvOutput) { $row[$fCol] = \TYPO3\CMS\Backend\Utility\BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); } } } // Reset the ID if it was overwritten if (strlen($this->searchString)) { $this->id = $id_orig; } // Add row to CSV list: if ($this->csvOutput) { $this->addToCSV($row, $table); } // Add classes to table cells $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass; if (!$this->dontShowClipControlPanels) { $this->addElement_tdCssClass['_CONTROL_'] = 'col-control'; $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space'; $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard'; } $this->addElement_tdCssClass['_PATH_'] = 'col-path'; $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa'; $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb'; // Create element in table cells: $iOut .= $this->addelement(1, $theIcon, $theData, $row_bgColor); // Finally, return table row element: return $iOut; } }
/** * Render the control-icons for a record header (create new, sorting, delete, disable/enable). * Most of the parts are copy&paste from TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList and * modified for the JavaScript calls here * * @param array $data Current data * @return string The HTML code with the control-icons */ protected function renderForeignRecordHeaderControl(array $data) { $rec = $data['databaseRow']; $inlineConfig = $data['inlineParentConfig']; $foreignTable = $inlineConfig['foreign_table']; $languageService = $this->getLanguageService(); $backendUser = $this->getBackendUserAuthentication(); // Initialize: $cells = array(); $additionalCells = array(); $isNewItem = substr($rec['uid'], 0, 3) == 'NEW'; $isParentExisting = MathUtility::canBeInterpretedAsInteger($data['inlineParentUid']); $tcaTableCtrl =& $GLOBALS['TCA'][$foreignTable]['ctrl']; $tcaTableCols =& $GLOBALS['TCA'][$foreignTable]['columns']; $isPagesTable = $foreignTable === 'pages'; $isSysFileReferenceTable = $foreignTable === 'sys_file_reference'; $enableManualSorting = $tcaTableCtrl['sortby'] || $inlineConfig['MM'] || !$data['isOnSymmetricSide'] && $inlineConfig['foreign_sortby'] || $data['isOnSymmetricSide'] && $inlineConfig['symmetric_sortby']; $nameObject = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($data['inlineFirstPid']); $nameObjectFt = $nameObject . '-' . $foreignTable; $nameObjectFtId = $nameObjectFt . '-' . $rec['uid']; $calcPerms = $backendUser->calcPerms(BackendUtility::readPageAccess($rec['pid'], $backendUser->getPagePermsClause(1))); // If the listed table is 'pages' we have to request the permission settings for each page: $localCalcPerms = false; if ($isPagesTable) { $localCalcPerms = $backendUser->calcPerms(BackendUtility::getRecord('pages', $rec['uid'])); } // This expresses the edit permissions for this particular element: $permsEdit = $isPagesTable && $localCalcPerms & Permission::PAGE_EDIT || !$isPagesTable && $calcPerms & Permission::CONTENT_EDIT; // Controls: Defines which controls should be shown $enabledControls = $inlineConfig['appearance']['enabledControls']; // Hook: Can disable/enable single controls for specific child records: foreach ($this->hookObjects as $hookObj) { /** @var InlineElementHookInterface $hookObj */ $hookObj->renderForeignRecordHeaderControl_preProcess($data['inlineParentUid'], $foreignTable, $rec, $inlineConfig, $data['isInlineDefaultLanguageRecordInLocalizedParentContext'], $enabledControls); } if ($data['isInlineDefaultLanguageRecordInLocalizedParentContext']) { $cells['localize.isLocalizable'] = '<span title="' . $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:localize.isLocalizable', true) . '">' . $this->iconFactory->getIcon('actions-edit-localize-status-low', Icon::SIZE_SMALL)->render() . '</span>'; } // "Info": (All records) if ($enabledControls['info'] && !$isNewItem) { if ($rec['table_local'] === 'sys_file') { $uid = (int) substr($rec['uid_local'], 9); $table = '_FILE'; } else { $uid = $rec['uid']; $table = $foreignTable; } $cells['info'] = ' <a class="btn btn-default" href="#" onclick="' . htmlspecialchars('top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($uid) . '); return false;') . '" title="' . $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:showInfo', true) . '"> ' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . ' </a>'; } // If the table is NOT a read-only table, then show these links: if (!$tcaTableCtrl['readOnly'] && !$data['isInlineDefaultLanguageRecordInLocalizedParentContext']) { // "New record after" link (ONLY if the records in the table are sorted by a "sortby"-row or if default values can depend on previous record): if ($enabledControls['new'] && ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues'])) { if (!$isPagesTable && $calcPerms & Permission::CONTENT_EDIT || $isPagesTable && $calcPerms & Permission::PAGE_NEW) { $onClick = 'return inline.createNewRecord(' . GeneralUtility::quoteJSvalue($nameObjectFt) . ',' . GeneralUtility::quoteJSvalue($rec['uid']) . ')'; $style = ''; if ($inlineConfig['inline']['inlineNewButtonStyle']) { $style = ' style="' . $inlineConfig['inline']['inlineNewButtonStyle'] . '"'; } $cells['new'] = ' <a class="btn btn-default inlineNewButton ' . $this->inlineData['config'][$nameObject]['md5'] . '" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:new' . ($isPagesTable ? 'Page' : 'Record'), true) . '" ' . $style . '> ' . $this->iconFactory->getIcon('actions-' . ($isPagesTable ? 'page' : 'document') . '-new', Icon::SIZE_SMALL)->render() . ' </a>'; } } // "Up/Down" links if ($enabledControls['sort'] && $permsEdit && $enableManualSorting) { // Up $onClick = 'return inline.changeSorting(' . GeneralUtility::quoteJSvalue($nameObjectFtId) . ', \'1\')'; $style = $inlineConfig['inline']['first'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; $cells['sort.up'] = ' <a class="btn btn-default sortingUp" href="#" onclick="' . htmlspecialchars($onClick) . '" ' . $style . ' title="' . $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:moveUp', true) . '"> ' . $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . ' </a>'; // Down $onClick = 'return inline.changeSorting(' . GeneralUtility::quoteJSvalue($nameObjectFtId) . ', \'-1\')'; $style = $inlineConfig['inline']['last'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; $cells['sort.down'] = ' <a class="btn btn-default sortingDown" href="#" onclick="' . htmlspecialchars($onClick) . '" ' . $style . ' title="' . $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:moveDown', true) . '"> ' . $this->iconFactory->getIcon('actions-move-down', Icon::SIZE_SMALL)->render() . ' </a>'; } // "Edit" link: if ($rec['table_local'] === 'sys_file' && !$isNewItem) { $sys_language_uid = 0; if (!empty($rec['sys_language_uid'])) { $sys_language_uid = $rec['sys_language_uid'][0]; } $recordInDatabase = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', 'sys_file_metadata', 'file = ' . (int) substr($rec['uid_local'], 9) . ' AND sys_language_uid = ' . $sys_language_uid); if ($backendUser->check('tables_modify', 'sys_file_metadata')) { $url = BackendUtility::getModuleUrl('record_edit', array('edit[sys_file_metadata][' . (int) $recordInDatabase['uid'] . ']' => 'edit')); $editOnClick = 'if (top.content.list_frame) {' . 'top.content.list_frame.location.href=' . GeneralUtility::quoteJSvalue($url . '&returnUrl=') . '+top.rawurlencode(top.content.list_frame.document.location.pathname+top.content.list_frame.document.location.search)' . ';' . '}'; $title = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:cm.editMetadata'); $cells['editmetadata'] = ' <a class="btn btn-default" href="#" class="btn" onclick="' . htmlspecialchars($editOnClick) . '" title="' . htmlspecialchars($title) . '"> ' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . ' </a>'; } } // "Delete" link: if ($enabledControls['delete'] && ($isPagesTable && $localCalcPerms & Permission::PAGE_DELETE || !$isPagesTable && $calcPerms & Permission::CONTENT_EDIT || $isSysFileReferenceTable && $calcPerms & Permission::PAGE_EDIT)) { $title = $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:delete', true); $icon = $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(); $cells['delete'] = '<a href="#" class="btn btn-default t3js-editform-delete-inline-record" data-objectid="' . htmlspecialchars($nameObjectFtId) . '" title="' . $title . '">' . $icon . '</a>'; } // "Hide/Unhide" links: $hiddenField = $tcaTableCtrl['enablecolumns']['disabled']; if ($enabledControls['hide'] && $permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $backendUser->check('non_exclude_fields', $foreignTable . ':' . $hiddenField))) { $onClick = 'return inline.enableDisableRecord(' . GeneralUtility::quoteJSvalue($nameObjectFtId) . ')'; $className = 't3js-' . $nameObjectFtId . '_disabled'; if ($rec[$hiddenField]) { $title = $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:unHide' . ($isPagesTable ? 'Page' : ''), true); $cells['hide.unhide'] = ' <a class="btn btn-default hiddenHandle ' . $className . '" href="#" onclick="' . htmlspecialchars($onClick) . '"' . 'title="' . $title . '">' . $this->iconFactory->getIcon('actions-edit-unhide', Icon::SIZE_SMALL)->render() . ' </a>'; } else { $title = $languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:hide' . ($isPagesTable ? 'Page' : ''), true); $cells['hide.hide'] = ' <a class="btn btn-default hiddenHandle ' . $className . '" href="#" onclick="' . htmlspecialchars($onClick) . '"' . 'title="' . $title . '">' . $this->iconFactory->getIcon('actions-edit-hide', Icon::SIZE_SMALL)->render() . ' </a>'; } } // Drag&Drop Sorting: Sortable handler for script.aculo.us if ($enabledControls['dragdrop'] && $permsEdit && $enableManualSorting && $inlineConfig['appearance']['useSortable']) { $additionalCells['dragdrop'] = ' <span class="btn btn-default sortableHandle" data-id="' . htmlspecialchars($rec['uid']) . '" title="' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.move', true) . '"> ' . $this->iconFactory->getIcon('actions-move-move', Icon::SIZE_SMALL)->render() . ' </span>'; } } elseif ($data['isInlineDefaultLanguageRecordInLocalizedParentContext'] && $isParentExisting) { if ($enabledControls['localize'] && $data['isInlineDefaultLanguageRecordInLocalizedParentContext']) { $onClick = 'inline.synchronizeLocalizeRecords(' . GeneralUtility::quoteJSvalue($nameObjectFt) . ', ' . GeneralUtility::quoteJSvalue($rec['uid']) . ');'; $cells['localize'] = ' <a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:localize', true) . '"> ' . $this->iconFactory->getIcon('actions-document-localize', Icon::SIZE_SMALL)->render() . ' </a>'; } } // If the record is edit-locked by another user, we will show a little warning sign: if ($lockInfo = BackendUtility::isRecordLocked($foreignTable, $rec['uid'])) { $cells['locked'] = ' <a class="btn btn-default" href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;"> ' . '<span title="' . htmlspecialchars($lockInfo['msg']) . '">' . $this->iconFactory->getIcon('status-warning-in-use', Icon::SIZE_SMALL)->render() . '</span>' . ' </a>'; } // Hook: Post-processing of single controls for specific child records: foreach ($this->hookObjects as $hookObj) { $hookObj->renderForeignRecordHeaderControl_postProcess($data['inlineParentUid'], $foreignTable, $rec, $inlineConfig, $data['isInlineDefaultLanguageRecordInLocalizedParentContext'], $cells); } $out = ''; if (!empty($cells)) { $out .= ' <div class="btn-group btn-group-sm" role="group">' . implode('', $cells) . '</div>'; } if (!empty($additionalCells)) { $out .= ' <div class="btn-group btn-group-sm" role="group">' . implode('', $additionalCells) . '</div>'; } return $out; }
/** * Rendering the quick-edit view. * * @return string */ public function renderQuickEdit() { $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $lang = $this->getLanguageService(); // Alternative template $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout_quickedit.html'); // Alternative form tag; Quick Edit submits its content to tce_db.php. $this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">'; // Setting up the context sensitive menu: $this->doc->getContextMenuCode(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND colPos=' . (int) substr($edit_record, 10) . ' AND sys_language_uid=' . (int) $this->current_sys_language . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = BackendUtility::getModuleUrl('record_edit', array('edit[tt_content][' . implode(',', $idListA) . ']' => 'edit', 'returnUrl' => $this->local_linkThisScript(array('edit_record' => '')))); HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $databaseConnection->exec_SELECTquery('*', 'sys_log', 'userid=' . (int) $beUser->user['uid'] . ' AND NEWid=' . $databaseConnection->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $databaseConnection->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } // Creating the selector box, allowing the user to select which element to edit: $opt = array(); $is_selected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int) $this->current_sys_language); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editLanguageHeader', TRUE) . ' ]</option>'; } else { $inValue = 'pages:' . $this->id; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editPageProperties', TRUE) . ' ]</option>'; } // Selecting all content elements from this language and allowed colPos: $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND sys_language_uid=' . (int) $this->current_sys_language . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $colPos = NULL; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (!isset($colPos) || $cRow['colPos'] !== $colPos) { $colPos = $cRow['colPos']; $opt[] = '<option value=""></option>'; $opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), TRUE) . ':__</option>'; } $inValue = 'tt_content:' . $cRow['uid']; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $beUser->uc['titleLen'])) . '</option>'; $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('newLabel', 1) . ' ]</option>'; } // If none is yet selected... if (!$is_selected) { $opt[] = '<option value=""></option>'; $opt[] = '<option value="' . $edit_record . '" selected="selected">[ ' . $lang->getLL('newLabel', TRUE) . ' ]</option>'; } // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); // Delete-button flag? $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($this->eRParts[0] != 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] == 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = FALSE; $undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($this->eRParts[0], 'sys_history') . ' AND recuid=' . (int) $this->eRParts[1], '', 'tstamp DESC', '1'); if ($this->undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) { $this->undoButton = TRUE; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1))); if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } // Return-url for JavaScript: $retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+' . GeneralUtility::quoteJSvalue(rawurlencode($this->returnUrl)) : ''; // Drawing the edit record selectbox $this->editSelect = '<select name="edit_record" onchange="' . htmlspecialchars('jumpToUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('web_layout') . '&id=' . $this->id . '&edit_record=') . '+escape(this.options[this.selectedIndex].value)' . $retUrlStr . ',this);') . '">' . implode('', $opt) . '</select>'; $content = ''; // Creating editing form: if ($beUser->check('tables_modify', $this->eRParts[0]) && $edit_record && ($this->eRParts[0] !== 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] === 'pages' && $this->CALC_PERMS & Permission::PAGE_SHOW)) { // Splitting uid parts for special features, if new: list($uidVal, $ex_pid, $ex_colPos) = explode('/', $this->eRParts[1]); // Convert $uidVal to workspace version if any: if ($uidVal != 'new') { if ($draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $this->eRParts[0], $uidVal, 'uid')) { $uidVal = $draftRecord['uid']; } } // Initializing transfer-data object: $trData = GeneralUtility::makeInstance(DataPreprocessor::class); $trData->addRawData = TRUE; $trData->defVals[$this->eRParts[0]] = array('colPos' => (int) $ex_colPos, 'sys_language_uid' => (int) $this->current_sys_language); $trData->lockRecords = 1; // 'new' $trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal); $new_unique_uid = ''; // Getting/Making the record: reset($trData->regTableItems_data); $rec = current($trData->regTableItems_data); if ($uidVal == 'new') { $new_unique_uid = uniqid('NEW', TRUE); $rec['uid'] = $new_unique_uid; $rec['pid'] = (int) $ex_pid ?: $this->id; $recordAccess = TRUE; } else { $rec['uid'] = $uidVal; // Checking internals access: $recordAccess = $beUser->recordEditAccessInternals($this->eRParts[0], $uidVal); } if (!$recordAccess) { // If no edit access, print error message: $content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : ''), 0, 1); } elseif (is_array($rec)) { // If the record is an array (which it will always be... :-) // Create instance of TCEforms, setting defaults: $tceForms = GeneralUtility::makeInstance(FormEngine::class); // Render form, wrap it: $panel = ''; $panel .= $tceForms->getMainFields($this->eRParts[0], $rec); $panel = $tceForms->wrapTotal($panel, $rec, $this->eRParts[0]); // Add hidden fields: $theCode = $panel; if ($uidVal == 'new') { $theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />'; } $theCode .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($uidVal == 'new' ? BackendUtility::getModuleUrl('web_layout', array('id' => $this->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl)) : $this->R_URI) . '" /> ' . FormEngine::getHiddenTokenField('tceAction'); // Add JavaScript as needed around the form: $theCode = $tceForms->printNeededJSFunctions_top() . $theCode . $tceForms->printNeededJSFunctions(); // Add warning sign if record was "locked": if ($lockInfo = BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } // Add whole form as a document section: $content = $this->doc->section('', $theCode); } } else { // If no edit access, print error message: $content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />', 0, 1); } // Bottom controls (function menus): $q_count = $this->getNumberOfHiddenElements(); if ($q_count) { $h_func_b = '<div class="checkbox">' . '<label for="checkTt_content_showHidden">' . BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"') . (!$q_count ? '<span class="text-muted">' . $lang->getLL('hiddenCE', TRUE) . '</span>' : $lang->getLL('hiddenCE', TRUE) . ' (' . $q_count . ')') . '</label>' . '</div>'; $content .= $this->doc->section('', $h_func_b, 0, 0); $content .= $this->doc->spacer(10); } // Select element matrix: if ($this->eRParts[0] == 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class); $posMap->backPath = $GLOBALS['BACK_PATH']; $posMap->cur_sys_language = $this->current_sys_language; $HTMLcode = ''; // CSH: $HTMLcode .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', NULL, '|<br />'); $HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); $content .= $this->doc->spacer(20); $content .= $this->doc->section($lang->getLL('CEonThisPage'), $HTMLcode, 0, 1); $content .= $this->doc->spacer(20); } return $content; }
/** * Draw the header for a single tt_content element * * @param array $row Record array * @param integer $space Amount of pixel space above the header. UNUSED * @param boolean $disableMoveAndNewButtons If set the buttons for creating new elements and moving up and down are not shown. * @param boolean $langMode If set, we are in language mode and flags will be shown for languages * @param boolean $dragDropEnabled If set the move button must be hidden * @return string HTML table with the record header. * @todo Define visibility */ 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: $params = '&edit[tt_content][' . $this->tt_contentData['nextThree'][$row['uid']] . ']=edit'; $out .= '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath, GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid'])) . '" title="' . htmlspecialchars($this->nextThree > 1 ? sprintf($this->getLanguageService()->getLL('nextThree'), $this->nextThree) : $this->getLanguageService()->getLL('edit')) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</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 href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params)) . '" title="' . $this->getLanguageService()->getLL($label, TRUE) . '">' . IconUtility::getSpriteIcon('actions-edit-' . strtolower($label)) . '</a>'; } // Delete $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1'; $confirm = GeneralUtility::quoteJSvalue($this->getLanguageService()->getLL('deleteWarning') . BackendUtility::translationCount('tt_content', $row['uid'], ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord'))); $out .= '<a href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params)) . '" onclick="' . htmlspecialchars('return confirm(' . $confirm . ');') . '" title="' . $this->getLanguageService()->getLL('deleteItem', TRUE) . '">' . IconUtility::getSpriteIcon('actions-edit-delete') . '</a>'; 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 href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params)) . '" title="' . $this->getLanguageService()->getLL('moveUp', TRUE) . '">' . IconUtility::getSpriteIcon('actions-move-up') . '</a>'; if (!$dragDropEnabled) { $displayMoveButtons = TRUE; } } else { $moveButtonContent .= IconUtility::getSpriteIcon('empty-empty'); } // 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 href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params)) . '" title="' . $this->getLanguageService()->getLL('moveDown', TRUE) . '">' . IconUtility::getSpriteIcon('actions-move-down') . '</a>'; if (!$dragDropEnabled) { $displayMoveButtons = TRUE; } } else { $moveButtonContent .= IconUtility::getSpriteIcon('empty-empty'); } if ($displayMoveButtons) { $out .= '<span class="t3-page-ce-icons-move">' . $moveButtonContent . '</span>'; } } } } $additionalIcons = array(); $additionalIcons[] = $this->getIcon('tt_content', $row) . ' '; $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']) . '">' . IconUtility::getSpriteIcon('status-warning-in-use') . '</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 '<h4 class="t3-page-ce-header"> <div class="t3-row-header"> <span class="ce-icons-left">' . implode('', $additionalIcons) . '</span> <span class="ce-icons"> ' . $out . ' </span></div> </h4> <div class="t3-page-ce-body">'; }
/** * Creates the editing form with FormEnigne, based on the input from GPvars. * * @return string HTML form elements wrapped in tables */ public function makeEditForm() { // Initialize variables: $this->elementsData = array(); $this->errorC = 0; $this->newC = 0; $editForm = ''; $trData = null; $beUser = $this->getBackendUser(); // Traverse the GPvar edit array // Tables: foreach ($this->editconf as $table => $conf) { if (is_array($conf) && $GLOBALS['TCA'][$table] && $beUser->check('tables_modify', $table)) { // Traverse the keys/comments of each table (keys can be a commalist of uids) foreach ($conf as $cKey => $command) { if ($command == 'edit' || $command == 'new') { // Get the ids: $ids = GeneralUtility::trimExplode(',', $cKey, true); // Traverse the ids: foreach ($ids as $theUid) { // Don't save this document title in the document selector if the document is new. if ($command === 'new') { $this->dontStoreDocumentRef = 1; } /** @var TcaDatabaseRecord $formDataGroup */ $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class); /** @var FormDataCompiler $formDataCompiler */ $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup); /** @var NodeFactory $nodeFactory */ $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); try { // Reset viewId - it should hold data of last entry only $this->viewId = 0; $this->viewId_addParams = ''; $formDataCompilerInput = ['tableName' => $table, 'vanillaUid' => (int) $theUid, 'command' => $command, 'returnUrl' => $this->R_URI]; if (is_array($this->overrideVals) && is_array($this->overrideVals[$table])) { $formDataCompilerInput['overrideValues'] = $this->overrideVals[$table]; } $formData = $formDataCompiler->compile($formDataCompilerInput); // Set this->viewId if possible if ($command === 'new' && $table !== 'pages' && !empty($formData['parentPageRow']['uid'])) { $this->viewId = $formData['parentPageRow']['uid']; } else { if ($table == 'pages') { $this->viewId = $formData['databaseRow']['uid']; } elseif (!empty($formData['parentPageRow']['uid'])) { $this->viewId = $formData['parentPageRow']['uid']; // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero! if (!empty($formData['processedTca']['ctrl']['languageField']) && is_array($formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']]) && $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0] > 0) { $this->viewId_addParams = '&L=' . $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0]; } } } // Determine if delete button can be shown $deleteAccess = false; if ($command === 'edit') { $permission = $formData['userPermissionOnPage']; if ($formData['tableName'] === 'pages') { $deleteAccess = $permission & Permission::PAGE_DELETE ? true : false; } else { $deleteAccess = $permission & Permission::CONTENT_EDIT ? true : false; } } // Display "is-locked" message: if ($command === 'edit') { $lockInfo = BackendUtility::isRecordLocked($table, $formData['databaseRow']['uid']); if ($lockInfo) { /** @var $flashMessage \TYPO3\CMS\Core\Messaging\FlashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } } // Record title if (!$this->storeTitle) { $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : BackendUtility::getRecordTitle($table, FormEngineUtility::databaseRowCompatibility($formData['databaseRow']), true); } $this->elementsData[] = array('table' => $table, 'uid' => $formData['databaseRow']['uid'], 'pid' => $formData['databaseRow']['pid'], 'cmd' => $command, 'deleteAccess' => $deleteAccess); if ($command !== 'new') { BackendUtility::lockRecords($table, $formData['databaseRow']['uid'], $table === 'tt_content' ? $formData['databaseRow']['pid'] : 0); } // Set list if only specific fields should be rendered. This will trigger // ListOfFieldsContainer instead of FullRecordContainer in OuterWrapContainer if ($this->columnsOnly) { if (is_array($this->columnsOnly)) { $formData['fieldListToRender'] = $this->columnsOnly[$table]; } else { $formData['fieldListToRender'] = $this->columnsOnly; } } $formData['renderType'] = 'outerWrapContainer'; $formResult = $nodeFactory->create($formData)->render(); $html = $formResult['html']; $formResult['html'] = ''; $formResult['doSaveFieldName'] = 'doSave'; // @todo: Put all the stuff into FormEngine as final "compiler" class // @todo: This is done here for now to not rewrite JStop() // @todo: and printNeededJSFunctions() now $this->formResultCompiler->mergeResult($formResult); // Seems the pid is set as hidden field (again) at end?! if ($command == 'new') { // @todo: looks ugly $html .= LF . '<input type="hidden"' . ' name="data[' . $table . '][' . $formData['databaseRow']['uid'] . '][pid]"' . ' value="' . $formData['databaseRow']['pid'] . '" />'; $this->newC++; } $editForm .= $html; } catch (AccessDeniedException $e) { $this->errorC++; // Try to fetch error message from "recordInternals" be user object // @todo: This construct should be logged and localized and de-uglified $message = $beUser->errorMsg; if (empty($message)) { // Create message from exception. $message = $e->getMessage() . ' ' . $e->getCode(); } $editForm .= $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noEditPermission', true) . '<br /><br />' . htmlspecialchars($message) . '<br /><br />'; } } // End of for each uid } } } } return $editForm; }
/** * Rendering the quick-edit view. * * @return void * @todo Define visibility */ public function renderQuickEdit() { // Alternative template $this->doc->setModuleTemplate('templates/db_layout_quickedit.html'); // Alternative form tag; Quick Edit submits its content to tce_db.php. $this->doc->form = '<form action="' . htmlspecialchars($GLOBALS['BACK_PATH'] . 'tce_db.php?&prErr=1&uPT=1') . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">'; // Setting up the context sensitive menu: $this->doc->getContextMenuCode(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to alt_doc.php: if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . intval($this->id) . ' AND colPos=' . intval(substr($edit_record, 10)) . ' AND sys_language_uid=' . intval($this->current_sys_language) . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('tt_content')) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content') . \TYPO3\CMS\Backend\Utility\BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = $GLOBALS['BACK_PATH'] . 'alt_doc.php?edit[tt_content][' . implode(',', $idListA) . ']=edit&returnUrl=' . rawurlencode($this->local_linkThisScript(array('edit_record' => ''))); \TYPO3\CMS\Core\Utility\HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_log', 'userid=' . intval($GLOBALS['BE_USER']->user['uid']) . ' AND NEWid=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } // Creating the selector box, allowing the user to select which element to edit: $opt = array(); $is_selected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . intval($this->current_sys_language)); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('editLanguageHeader', 1) . ' ]</option>'; } else { $inValue = 'pages:' . $this->id; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('editPageProperties', 1) . ' ]</option>'; } // Selecting all content elements from this language and allowed colPos: $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . intval($this->id) . ' AND sys_language_uid=' . intval($this->current_sys_language) . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('tt_content')) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content') . \TYPO3\CMS\Backend\Utility\BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $colPos = ''; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (strcmp($cRow['colPos'], $colPos)) { $colPos = $cRow['colPos']; $opt[] = '<option value=""></option>'; $opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $GLOBALS['LANG']->sL(\TYPO3\CMS\Backend\Utility\BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), 1) . ':__</option>'; } $inValue = 'tt_content:' . $cRow['uid']; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $GLOBALS['BE_USER']->uc['titleLen'])) . '</option>'; $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('newLabel', 1) . ' ]</option>'; } // If none is yet selected... if (!$is_selected) { $opt[] = '<option value=""></option>'; $opt[] = '<option value="' . $edit_record . '" selected="selected">[ ' . $GLOBALS['LANG']->getLL('newLabel', 1) . ' ]</option>'; } // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); // Delete-button flag? $this->deleteButton = \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($this->eRParts[0] != 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] == 'pages' && $this->CALC_PERMS & 4); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = 0; $undoRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->eRParts[0], 'sys_history') . ' AND recuid=' . intval($this->eRParts[1]), '', 'tstamp DESC', '1'); if ($this->undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) { $this->undoButton = 1; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1))); if ($GLOBALS['BE_USER']->uc['condensedMode']) { $this->closeUrl = $GLOBALS['BACK_PATH'] . 'alt_db_navframe.php'; } if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } // Return-url for JavaScript: $retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+\'' . rawurlencode($this->returnUrl) . '\'' : ''; // Drawing the edit record selectbox $this->editSelect = '<select name="edit_record" onchange="' . htmlspecialchars('jumpToUrl(\'db_layout.php?id=' . $this->id . '&edit_record=\'+escape(this.options[this.selectedIndex].value)' . $retUrlStr . ',this);') . '">' . implode('', $opt) . '</select>'; // Creating editing form: if ($GLOBALS['BE_USER']->check('tables_modify', $this->eRParts[0]) && $edit_record && ($this->eRParts[0] !== 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] === 'pages' && $this->CALC_PERMS & 1)) { // Splitting uid parts for special features, if new: list($uidVal, $ex_pid, $ex_colPos) = explode('/', $this->eRParts[1]); // Convert $uidVal to workspace version if any: if ($uidVal != 'new') { if ($draftRecord = \TYPO3\CMS\Backend\Utility\BackendUtility::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $this->eRParts[0], $uidVal, 'uid')) { $uidVal = $draftRecord['uid']; } } // Initializing transfer-data object: $trData = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\DataPreprocessor'); $trData->addRawData = TRUE; $trData->defVals[$this->eRParts[0]] = array('colPos' => intval($ex_colPos), 'sys_language_uid' => intval($this->current_sys_language)); $trData->disableRTE = $this->MOD_SETTINGS['disableRTE']; $trData->lockRecords = 1; // 'new' $trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal); // Getting/Making the record: reset($trData->regTableItems_data); $rec = current($trData->regTableItems_data); if ($uidVal == 'new') { $new_unique_uid = uniqid('NEW'); $rec['uid'] = $new_unique_uid; $rec['pid'] = intval($ex_pid) ? intval($ex_pid) : $this->id; $recordAccess = TRUE; } else { $rec['uid'] = $uidVal; // Checking internals access: $recordAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($this->eRParts[0], $uidVal); } if (!$recordAccess) { // If no edit access, print error message: $content .= $this->doc->section($GLOBALS['LANG']->getLL('noAccess'), $GLOBALS['LANG']->getLL('noAccess_msg') . '<br /><br />' . ($GLOBALS['BE_USER']->errorMsg ? 'Reason: ' . $GLOBALS['BE_USER']->errorMsg . '<br /><br />' : ''), 0, 1); } elseif (is_array($rec)) { // If the record is an array (which it will always be... :-) // Create instance of TCEforms, setting defaults: $tceforms = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\FormEngine'); $tceforms->backPath = $GLOBALS['BACK_PATH']; $tceforms->initDefaultBEMode(); $tceforms->fieldOrder = $this->modTSconfig['properties']['tt_content.']['fieldOrder']; $tceforms->palettesCollapsed = !$this->MOD_SETTINGS['showPalettes']; $tceforms->disableRTE = $this->MOD_SETTINGS['disableRTE']; $tceforms->enableClickMenu = TRUE; // Clipboard is initialized: // Start clipboard $tceforms->clipObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Clipboard\\Clipboard'); // Initialize - reads the clipboard content from the user session $tceforms->clipObj->initializeClipboard(); // Render form, wrap it: $panel = ''; $panel .= $tceforms->getMainFields($this->eRParts[0], $rec); $panel = $tceforms->wrapTotal($panel, $rec, $this->eRParts[0]); // Add hidden fields: $theCode = $panel; if ($uidVal == 'new') { $theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />'; } $theCode .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="_disableRTE" value="' . $tceforms->disableRTE . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($uidVal == 'new' ? \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('cms') . 'layout/db_layout.php?id=' . $this->id . '&new_unique_uid=' . $new_unique_uid . '&returnUrl=' . rawurlencode($this->returnUrl) : $this->R_URI) . '" /> ' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction'); // Add JavaScript as needed around the form: $theCode = $tceforms->printNeededJSFunctions_top() . $theCode . $tceforms->printNeededJSFunctions(); // Add warning sign if record was "locked": if ($lockInfo = \TYPO3\CMS\Backend\Utility\BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) { $lockedMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($lockInfo['msg']), '', \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING); \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($lockedMessage); } // Add whole form as a document section: $content .= $this->doc->section('', $theCode); } } else { // If no edit access, print error message: $content .= $this->doc->section($GLOBALS['LANG']->getLL('noAccess'), $GLOBALS['LANG']->getLL('noAccess_msg') . '<br /><br />', 0, 1); } // Bottom controls (function menus): $q_count = $this->getNumberOfHiddenElements(); $h_func_b = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], 'db_layout.php', '', 'id="checkTt_content_showHidden"') . '<label for="checkTt_content_showHidden">' . (!$q_count ? $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('hiddenCE', 1)) : $GLOBALS['LANG']->getLL('hiddenCE', 1) . ' (' . $q_count . ')') . '</label>'; $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[showPalettes]', $this->MOD_SETTINGS['showPalettes'], 'db_layout.php', '', 'id="checkShowPalettes"') . '<label for="checkShowPalettes">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPalettes', 1) . '</label>'; if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('context_help')) { $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[showDescriptions]', $this->MOD_SETTINGS['showDescriptions'], 'db_layout.php', '', 'id="checkShowDescriptions"') . '<label for="checkShowDescriptions">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showDescriptions', 1) . '</label>'; } if ($GLOBALS['BE_USER']->isRTE()) { $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[disableRTE]', $this->MOD_SETTINGS['disableRTE'], 'db_layout.php', '', 'id="checkDisableRTE"') . '<label for="checkDisableRTE">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.disableRTE', 1) . '</label>'; } // Add the function menus to bottom: $content .= $this->doc->section('', $h_func_b, 0, 0); $content .= $this->doc->spacer(10); // Select element matrix: if ($this->eRParts[0] == 'tt_content' && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $posMap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('ext_posMap'); $posMap->backPath = $GLOBALS['BACK_PATH']; $posMap->cur_sys_language = $this->current_sys_language; $HTMLcode = ''; // CSH: $HTMLcode .= \TYPO3\CMS\Backend\Utility\BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', $GLOBALS['BACK_PATH'], '|<br />'); $HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); $content .= $this->doc->spacer(20); $content .= $this->doc->section($GLOBALS['LANG']->getLL('CEonThisPage'), $HTMLcode, 0, 1); $content .= $this->doc->spacer(20); } // Finally, if comments were generated in TCEforms object, print these as a HTML comment: if (count($tceforms->commentMessages)) { $content .= ' <!-- TCEFORM messages ' . htmlspecialchars(implode(LF, $tceforms->commentMessages)) . ' --> '; } return $content; }
/** * Creates the editing form with TCEforms, based on the input from GPvars. * * @return string HTML form elements wrapped in tables */ public function makeEditForm() { // Initialize variables: $this->elementsData = array(); $this->errorC = 0; $this->newC = 0; $thePrevUid = ''; $editForm = ''; $trData = NULL; $beUser = $this->getBackendUser(); // Traverse the GPvar edit array // Tables: foreach ($this->editconf as $table => $conf) { if (is_array($conf) && $GLOBALS['TCA'][$table] && $beUser->check('tables_modify', $table)) { // Traverse the keys/comments of each table (keys can be a commalist of uids) foreach ($conf as $cKey => $cmd) { if ($cmd == 'edit' || $cmd == 'new') { // Get the ids: $ids = GeneralUtility::trimExplode(',', $cKey, TRUE); // Traverse the ids: foreach ($ids as $theUid) { // Checking if the user has permissions? (Only working as a precaution, // because the final permission check is always down in TCE. But it's // good to notify the user on beforehand...) // First, resetting flags. $hasAccess = 1; $deniedAccessReason = ''; $deleteAccess = 0; $this->viewId = 0; // If the command is to create a NEW record...: if ($cmd == 'new') { // NOTICE: the id values in this case points to the page uid onto which the // record should be create OR (if the id is negativ) to a record from the // same table AFTER which to create the record. if ((int) $theUid) { // Find parent page on which the new record reside // Less than zero - find parent page if ($theUid < 0) { $calcPRec = BackendUtility::getRecord($table, abs($theUid)); $calcPRec = BackendUtility::getRecord('pages', $calcPRec['pid']); } else { // always a page $calcPRec = BackendUtility::getRecord('pages', abs($theUid)); } // Now, calculate whether the user has access to creating new records on this position: if (is_array($calcPRec)) { // Permissions for the parent page $CALC_PERMS = $beUser->calcPerms($calcPRec); if ($table == 'pages') { // If pages: $hasAccess = $CALC_PERMS & Permission::PAGE_NEW ? 1 : 0; $this->viewId = 0; } else { $hasAccess = $CALC_PERMS & Permission::CONTENT_EDIT ? 1 : 0; $this->viewId = $calcPRec['uid']; } } } // Don't save this document title in the document selector if the document is new. $this->dontStoreDocumentRef = 1; } else { // Edit: $calcPRec = BackendUtility::getRecord($table, $theUid); BackendUtility::fixVersioningPid($table, $calcPRec); if (is_array($calcPRec)) { if ($table == 'pages') { // If pages: $CALC_PERMS = $beUser->calcPerms($calcPRec); $hasAccess = $CALC_PERMS & Permission::PAGE_EDIT ? 1 : 0; $deleteAccess = $CALC_PERMS & Permission::PAGE_DELETE ? 1 : 0; $this->viewId = $calcPRec['uid']; } else { // Fetching pid-record first $CALC_PERMS = $beUser->calcPerms(BackendUtility::getRecord('pages', $calcPRec['pid'])); $hasAccess = $CALC_PERMS & Permission::CONTENT_EDIT ? 1 : 0; $deleteAccess = $CALC_PERMS & Permission::CONTENT_EDIT ? 1 : 0; $this->viewId = $calcPRec['pid']; // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero! if ($GLOBALS['TCA'][$table]['ctrl']['languageField'] && $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) { $this->viewId_addParams = '&L=' . $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']]; } } // Check internals regarding access: $isRootLevelRestrictionIgnored = BackendUtility::isRootLevelRestrictionIgnored($table); if ($hasAccess || (int) $calcPRec['pid'] === 0 && $isRootLevelRestrictionIgnored) { $hasAccess = $beUser->recordEditAccessInternals($table, $calcPRec); $deniedAccessReason = $beUser->errorMsg; } } else { $hasAccess = 0; } } if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] as $_funcRef) { $_params = array('table' => $table, 'uid' => $theUid, 'cmd' => $cmd, 'hasAccess' => $hasAccess); $hasAccess = GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } // AT THIS POINT we have checked the access status of the editing/creation of // records and we can now proceed with creating the form elements: if ($hasAccess) { /** @var DataPreprocessor $trData */ $prevPageID = is_object($trData) ? $trData->prevPageID : ''; $trData = GeneralUtility::makeInstance(DataPreprocessor::class); $trData->addRawData = TRUE; $trData->defVals = $this->defVals; $trData->lockRecords = 1; $trData->prevPageID = $prevPageID; // 'new' $trData->fetchRecord($table, $theUid, $cmd == 'new' ? 'new' : ''); $rec = reset($trData->regTableItems_data); $rec['uid'] = $cmd == 'new' ? uniqid('NEW', TRUE) : $theUid; if ($cmd == 'new') { $rec['pid'] = $theUid == 'prev' ? $thePrevUid : $theUid; } $this->elementsData[] = array('table' => $table, 'uid' => $rec['uid'], 'pid' => $rec['pid'], 'cmd' => $cmd, 'deleteAccess' => $deleteAccess); // Now, render the form: if (is_array($rec)) { // Setting visual path / title of form: $this->generalPathOfForm = $this->tceforms->getRecordPath($table, $rec); if (!$this->storeTitle) { $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : BackendUtility::getRecordTitle($table, $rec, TRUE); } // Setting variables in TCEforms object: if (is_array($this->overrideVals) && is_array($this->overrideVals[$table])) { $this->tceforms->hiddenFieldListArr = array_keys($this->overrideVals[$table]); } // Create form for the record (either specific list of fields or the whole record): $panel = ''; if ($this->columnsOnly) { if (is_array($this->columnsOnly)) { $panel .= $this->tceforms->getListedFields($table, $rec, $this->columnsOnly[$table]); } else { $panel .= $this->tceforms->getListedFields($table, $rec, $this->columnsOnly); } } else { $panel .= $this->tceforms->getMainFields($table, $rec); } $panel = $this->tceforms->wrapTotal($panel, $rec, $table); // Setting the pid value for new records: if ($cmd == 'new') { $panel .= '<input type="hidden" name="data[' . $table . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />'; $this->newC++; } // Display "is-locked" message: if ($lockInfo = BackendUtility::isRecordLocked($table, $rec['uid'])) { /** @var $flashMessage \TYPO3\CMS\Core\Messaging\FlashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } // Combine it all: $editForm .= $panel; } $thePrevUid = $rec['uid']; } else { $this->errorC++; $editForm .= $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noEditPermission', TRUE) . '<br /><br />' . ($deniedAccessReason ? 'Reason: ' . htmlspecialchars($deniedAccessReason) . '<br /><br />' : ''); } } } } } } return $editForm; }
/** * Rendering a single row for the list * * @param string $table Table name * @param array $row Current record * @param integer $cc Counter, counting for each time an element is rendered (used for alternating colors) * @param string $titleCol Table field (column) where header value is found * @param string $thumbsCol Table field (column) where (possible) thumbnails can be found * @param integer $indent Indent from left. * @param integer $level * @return string Table row for the element * @access private * @see getTable() */ public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0, $level = 0) { $iOut = ''; // If in search mode, make sure the preview will show the correct page if (strlen($this->searchString)) { $id_orig = $this->id; $this->id = $row['pid']; } if (is_array($row)) { // Add special classes for first and last row $rowSpecial = ''; if ($cc == 1 && $indent == 0) { $rowSpecial .= ' firstcol'; } if ($cc == $this->totalRowCount || $cc == $this->iLimit) { $rowSpecial .= ' lastcol'; } // Background color, if any: if ($this->alternateBgColors) { $row_bgColor = $cc % 2 ? ' class="db_list_normal' . $rowSpecial . '"' : ' class="db_list_alt' . $rowSpecial . '"'; } else { $row_bgColor = ' class="db_list_normal' . $rowSpecial . '"'; } // Overriding with versions background color if any: $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor; // Incr. counter. $this->counter++; // The icon with link $alttext = BackendUtility::getRecordIconAltText($row, $table); $iconImg = IconUtility::getSpriteIconForRecord($table, $row, array('title' => htmlspecialchars($alttext), 'style' => $indent ? ' margin-left: ' . $indent . 'px;' : '')); $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg; // Preparing and getting the data-array $theData = array(); foreach ($this->fieldArray as $fCol) { if ($fCol == $titleCol) { $recTitle = BackendUtility::getRecordTitle($table, $row, FALSE, TRUE); // If the record is edit-locked by another user, we will show a little warning sign: if ($lockInfo = BackendUtility::isRecordLocked($table, $row['uid'])) { $warning = '<a href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . '); return false;" title="' . htmlspecialchars($lockInfo['msg']) . '">' . IconUtility::getSpriteIcon('status-warning-in-use') . '</a>'; } $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row); // Render thumbnails, if: // - a thumbnail column exists // - there is content in it // - the thumbnail column is visible for the current type $type = 0; if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) { $typeColumn = $GLOBALS['TCA'][$table]['ctrl']['type']; $type = $row[$typeColumn]; } // If current type doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist) if (!isset($GLOBALS['TCA'][$table]['types'][$type])) { $type = isset($GLOBALS['TCA'][$table]['types'][0]) ? 0 : 1; } $visibleColumns = $GLOBALS['TCA'][$table]['types'][$type]['showitem']; if ($this->thumbs && trim($row[$thumbsCol]) && preg_match('/(^|(.*(;|,)?))' . $thumbsCol . '(((;|,).*)|$)/', $visibleColumns) === 1) { $theData[$fCol] .= '<br />' . $this->thumbCode($row, $table, $thumbsCol); } $localizationMarkerClass = ''; if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { // It's a translated record with a language parent $localizationMarkerClass = ' localization'; } } elseif ($fCol == 'pid') { $theData[$fCol] = $row[$fCol]; } elseif ($fCol == '_PATH_') { $theData[$fCol] = $this->recPath($row['pid']); } elseif ($fCol == '_REF_') { $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']); } elseif ($fCol == '_CONTROL_') { $theData[$fCol] = $this->makeControl($table, $row, $level); } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') { $theData[$fCol] = ' '; } elseif ($fCol == '_CLIPBOARD_') { $theData[$fCol] = $this->makeClip($table, $row); } elseif ($fCol == '_LOCALIZATION_') { list($lC1, $lC2) = $this->makeLocalizationPanel($table, $row); $theData[$fCol] = $lC1; } elseif (!$fCol == '_LOCALIZATION_b') { $tmpProc = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']); $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); if ($this->csvOutput) { $row[$fCol] = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); } } elseif ($fCol == '_LOCALIZATION_b') { $theData[$fCol] = $lC2; } else { $tmpProc = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']); $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); if ($this->csvOutput) { $row[$fCol] = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); } } } // Reset the ID if it was overwritten if (strlen($this->searchString)) { $this->id = $id_orig; } // Add row to CSV list: if ($this->csvOutput) { $this->addToCSV($row, $table); } // Add classes to table cells $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass; if (!$this->dontShowClipControlPanels) { $this->addElement_tdCssClass['_CONTROL_'] = 'col-control'; $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space'; $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard'; } $this->addElement_tdCssClass['_PATH_'] = 'col-path'; $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa'; $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb'; /** * @hook checkChildren * @date 2014-02-11 * @request Alexander Grein <*****@*****.**> */ if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classData); if (!$this->searchString && is_object($hookObject) && method_exists($hookObject, 'checkChildren')) { $hookObject->checkChildren($table, $row, $level, $theData, $this); } } } // Create element in table cells: $iOut .= $this->addelement(1, $theIcon, $theData, $row_bgColor, '', '', $level); // Finally, return table row element: if ($cc > 0 || !$this->csvOutput) { return $iOut; } else { return ''; } } }
/** * Rendering a single row for the list * * @param string $table Table name * @param mixed[] $row Current record * @param int $cc Counter, counting for each time an element is rendered (used for alternating colors) * @param string $titleCol Table field (column) where header value is found * @param string $thumbsCol Table field (column) where (possible) thumbnails can be found * @param int $indent Indent from left. * @param integer $level * @param string $expanded * * @return string Table row for the element * @access private * @see getTable() */ public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0, $level = 0, $expanded = '') { if (!is_array($row)) { return ''; } $rowOutput = ''; $id_orig = null; // If in search mode, make sure the preview will show the correct page if ((string) $this->searchString !== '') { $id_orig = $this->id; $this->id = $row['pid']; } // Add special classes for first and last row $rowSpecial = ''; if ($cc == 1 && $indent == 0) { $rowSpecial .= ' firstcol'; } if ($cc == $this->totalRowCount || $cc == $this->iLimit) { $rowSpecial .= ' lastcol'; } $row_bgColor = ' class="' . $rowSpecial . '"'; // Overriding with versions background color if any: $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor; // Incr. counter. $this->counter++; // The icon with link $altText = BackendUtility::getRecordIconAltText($row, $table); $additionalStyle = $indent ? ' style="margin-left: ' . $indent . 'px;"' : ''; $iconImg = '<span title="' . $altText . '" ' . $additionalStyle . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>'; $theIcon = $this->clickMenuEnabled ? BackendUtility::wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg; // Preparing and getting the data-array $theData = array(); $localizationMarkerClass = ''; $lC2 = ''; foreach ($this->fieldArray as $fCol) { if ($fCol == $titleCol) { $recTitle = BackendUtility::getRecordTitle($table, $row, false, true); $warning = ''; // If the record is edit-locked by another user, we will show a little warning sign: $lockInfo = BackendUtility::isRecordLocked($table, $row['uid']); if ($lockInfo) { $warning = '<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>'; } $theData[$fCol] = $theData['__label'] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row); // Render thumbnails, if: // - a thumbnail column exists // - there is content in it // - the thumbnail column is visible for the current type $type = 0; if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) { $typeColumn = $GLOBALS['TCA'][$table]['ctrl']['type']; $type = $row[$typeColumn]; } // If current type doesn't exist, set it to 0 (or to 1 for historical reasons, // if 0 doesn't exist) if (!isset($GLOBALS['TCA'][$table]['types'][$type])) { $type = isset($GLOBALS['TCA'][$table]['types'][0]) ? 0 : 1; } $visibleColumns = $GLOBALS['TCA'][$table]['types'][$type]['showitem']; if ($this->thumbs && trim($row[$thumbsCol]) && preg_match('/(^|(.*(;|,)?))' . $thumbsCol . '(((;|,).*)|$)/', $visibleColumns) === 1) { $theData[$fCol] .= '<br />' . $this->thumbCode($row, $table, $thumbsCol); } if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { // It's a translated record with a language parent $localizationMarkerClass = ' localization'; } } elseif ($fCol == 'pid') { $theData[$fCol] = $row[$fCol]; } elseif ($fCol == '_PATH_') { $theData[$fCol] = $this->recPath($row['pid']); } elseif ($fCol == '_REF_') { $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']); } elseif ($fCol == '_CONTROL_') { $theData[$fCol] = $this->makeControl($table, $row, $level); } elseif ($fCol == '_CLIPBOARD_') { $theData[$fCol] = $this->makeClip($table, $row); } elseif ($fCol == '_LOCALIZATION_') { list($lC1, $lC2) = $this->makeLocalizationPanel($table, $row); $theData[$fCol] = $lC1; } elseif ($fCol != '_LOCALIZATION_b') { $tmpProc = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']); $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); if ($this->csvOutput) { $row[$fCol] = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); } } elseif ($fCol == '_LOCALIZATION_b') { $theData[$fCol] = $lC2; } else { $theData[$fCol] = htmlspecialchars(BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid'])); } } // Reset the ID if it was overwritten if ((string) $this->searchString !== '') { $this->id = $id_orig; } // Add row to CSV list: if ($this->csvOutput) { $this->addToCSV($row); } // Add classes to table cells $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass; $this->addElement_tdCssClass['_CONTROL_'] = 'col-control'; if ($this->getModule()->MOD_SETTINGS['clipBoard']) { $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard'; } $this->addElement_tdCssClass['_PATH_'] = 'col-path'; $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa'; $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb'; /** * @hook checkChildren * @date 2014-02-11 * @request Alexander Grein <*****@*****.**> */ if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { $hookObject = GeneralUtility::getUserObj($classData); if (is_object($hookObject) && method_exists($hookObject, 'checkChildren')) { $hookObject->checkChildren($table, $row, $level, $theData, $this); } } } // Create element in table cells: $theData['uid'] = $row['uid']; if ($table === 'tt_content') { $theData['tx_gridelements_container'] = $row['tx_gridelements_container']; } if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) { $theData['parent'] = $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; } $rowOutput .= $this->addElement(1, $theIcon, $theData, $row_bgColor, '', '', '', $level); if ($this->localizationView && $this->l10nEnabled) { // For each available translation, render the record: if (is_array($this->translations)) { foreach ($this->translations as $lRow) { // $lRow isn't always what we want - if record was moved we've to work with the // placeholder records otherwise the list is messed up a bit if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) { $where = 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table); $tmpRow = BackendUtility::getRecordRaw($table, $where, $this->selFieldList); $lRow = is_array($tmpRow) ? $tmpRow : $lRow; } // In offline workspace, look for alternative record: BackendUtility::workspaceOL($table, $lRow, $this->backendUser->workspace, true); if (is_array($lRow) && $this->backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) { $this->currentIdList[] = $lRow['uid']; if ($row['tx_gridelements_container']) { $lRow['_CSSCLASS'] = 't3-gridelements-child" data-trigger-container="' . $row['tx_gridelements_container'] . $expanded; } $rowOutput .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 20, $level); } } } } if ($theData['_EXPANDABLE_'] && $level < 8 && ($row['l18n_parent'] == 0 || !$this->localizationView)) { if (!empty($theData['_CHILDREN_'])) { $expanded = $this->expandedGridelements[$row['uid']] ? '" style="display: table-row;' : ''; $lastGridColumn = ''; $originalMoveUp = $this->showMoveUp; $originalMoveDown = $this->showMoveDown; $prevPrevUid = (int) $theData['_CHILDREN_'][0]['uid']; $prevUid = (int) $theData['_CHILDREN_'][1]['uid']; foreach ($theData['_CHILDREN_'] as $key => $child) { if ($key > 1) { if ($prevUid) { $this->currentTable['prev'][$child['uid']] = $prevPrevUid; $this->currentTable['next'][$prevUid] = -(int) $child['uid']; $this->currentTable['prevUid'][$child['uid']] = $prevUid; } $prevPrevUid = isset($this->currentTable['prev'][$child['uid']]) ? -$prevUid : $row['pid']; $prevUid = $child['uid']; } } foreach ($theData['_CHILDREN_'] as $key => $child) { if (isset($child['tx_gridelements_columns']) && $child['tx_gridelements_columns'] != $lastGridColumn) { $lastGridColumn = $child['tx_gridelements_columns']; $this->showMoveUp = false; $rowOutput .= '<tr class="t3-gridelements-child" data-trigger-container="' . ($this->localizationView && $row['l18n_parent'] ? $row['l18n_parent'] : $row['uid']) . $expanded . '" data-grid-container="' . $row['uid'] . '"> <td colspan="2"></td> <td colspan="' . (count($this->fieldArray) - 1 + $this->maxDepth) . '" style="padding:5px;"> <br /> <strong>' . $this->getLanguageService()->sL('LLL:EXT:gridelements/Resources/Private/Language/locallang_db.xml:list.columnName') . ' ' . ($backendLayoutColumns[$child['tx_gridelements_columns']] ? $backendLayoutColumns[$child['tx_gridelements_columns']] : (int) $child['tx_gridelements_columns']) . '</strong> </td> </tr>'; } else { $this->showMoveUp = true; } if (isset($child['tx_gridelements_columns']) && isset($theData['_CHILDREN_'][$key + 1]) && $child['tx_gridelements_columns'] != $theData['_CHILDREN_'][$key + 1]['tx_gridelements_columns']) { $this->showMoveDown = false; } else { $this->showMoveDown = true; } $this->currentIdList[] = $child['uid']; if ($row['CType'] === 'gridelements_pi1') { $this->currentContainerIdList[] = $row['uid']; } $child['_CSSCLASS'] = 't3-gridelements-child" data-trigger-container="' . ($this->localizationView && $row['l18n_parent'] ? $row['l18n_parent'] : $row['uid']) . $expanded; $rowOutput .= $this->renderListRow($table, $child, $cc, $titleCol, $thumbsCol, 0, $level + 1, $expanded); } $this->showMoveUp = $originalMoveUp; $this->showMoveDown = $originalMoveDown; } } // Finally, return table row element: return $rowOutput; }