/** * @test * @dataProvider getLabelFromItemlistReturnsCorrectFieldsDataProvider */ public function getLabelFromItemlistReturnsCorrectFields($table, $col = '', $key = '', array $tca, $expectedLabel = '') { \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($table); $tcaBackup = $GLOBALS['TCA'][$table]; unset($GLOBALS['TCA'][$table]); $GLOBALS['TCA'][$table] = $tca; $label = $this->fixture->getLabelFromItemlist($table, $col, $key); unset($GLOBALS['TCA'][$table]); $GLOBALS['TCA'][$table] = $tcaBackup; $this->assertEquals($label, $expectedLabel); }
/** * Draws the preview content for a content element * * @param array $row Content element * @return string HTML * @throws \UnexpectedValueException */ public function tt_content_drawItem($row) { $out = ''; $outHeader = ''; // Make header: if ($row['header']) { $infoArr = array(); $this->getProcessedValue('tt_content', 'header_position,header_layout,header_link', $row, $infoArr); $hiddenHeaderNote = ''; // If header layout is set to 'hidden', display an accordant note: if ($row['header_layout'] == 100) { $hiddenHeaderNote = ' <em>[' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.hidden', true) . ']</em>'; } $outHeader = $row['date'] ? htmlspecialchars($this->itemLabels['date'] . ' ' . BackendUtility::date($row['date'])) . '<br />' : ''; $outHeader .= '<strong>' . $this->linkEditContent($this->renderText($row['header']), $row) . $hiddenHeaderNote . '</strong><br />'; } // Make content: $infoArr = array(); $drawItem = true; // Hook: Render an own preview of a record $drawItemHooks =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']; if (is_array($drawItemHooks)) { foreach ($drawItemHooks as $hookClass) { $hookObject = GeneralUtility::getUserObj($hookClass); if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) { throw new \UnexpectedValueException('$hookObject must implement interface ' . \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface::class, 1218547409); } $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row); } } // If the previous hook did not render something, // then check if a Fluid-based preview template was defined for this CType // and render it via Fluid. Possible option: // mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html if ($drawItem) { $tsConfig = BackendUtility::getModTSconfig($row['pid'], 'mod.web_layout.tt_content.preview'); if (!empty($tsConfig['properties'][$row['CType']])) { $fluidTemplateFile = $tsConfig['properties'][$row['CType']]; $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile); if ($fluidTemplateFile) { try { /** @var StandaloneView $view */ $view = GeneralUtility::makeInstance(StandaloneView::class); $view->setTemplatePathAndFilename($fluidTemplateFile); $view->assignMultiple($row); if (!empty($row['pi_flexform'])) { /** @var FlexFormService $flexFormService */ $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); $view->assign('pi_flexform_transformed', $flexFormService->convertFlexFormContentToArray($row['pi_flexform'])); } $out = $view->render(); $drawItem = false; } catch (\Exception $e) { // Catch any exception to avoid breaking the view } } } } // Draw preview of the item depending on its CType (if not disabled by previous hook): if ($drawItem) { switch ($row['CType']) { case 'header': if ($row['subheader']) { $out .= $this->linkEditContent($this->renderText($row['subheader']), $row) . '<br />'; } break; case 'bullets': case 'table': if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } break; case 'uploads': if ($row['media']) { $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'media'), $row) . '<br />'; } break; case 'menu': $contentType = $this->CType_labels[$row['CType']]; $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />'; // Add Menu Type $menuTypeLabel = $this->getLanguageService()->sL(BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'menu_type', $row['menu_type'])); $menuTypeLabel = $menuTypeLabel ?: 'invalid menu type'; $out .= $this->linkEditContent($menuTypeLabel, $row); if ($row['menu_type'] !== '2' && ($row['pages'] || $row['selected_categories'])) { // Show pages if menu type is not "Sitemap" $out .= ':' . $this->linkEditContent($this->generateListForCTypeMenu($row), $row) . '<br />'; } break; case 'shortcut': if (!empty($row['records'])) { $shortcutContent = array(); $recordList = explode(',', $row['records']); foreach ($recordList as $recordIdentifier) { $split = BackendUtility::splitTable_Uid($recordIdentifier); $tableName = empty($split[0]) ? 'tt_content' : $split[0]; $shortcutRecord = BackendUtility::getRecord($tableName, $split[1]); if (is_array($shortcutRecord)) { $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord, Icon::SIZE_SMALL)->render(); $icon = BackendUtility::wrapClickMenuOnIcon($icon, $tableName, $shortcutRecord['uid'], 1, '', '+copy,info,edit,view'); $shortcutContent[] = $icon . htmlspecialchars(BackendUtility::getRecordTitle($tableName, $shortcutRecord)); } } $out .= implode('<br />', $shortcutContent) . '<br />'; } break; case 'list': $hookArr = array(); $hookOut = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']]; } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT']; } if (!empty($hookArr)) { $_params = array('pObj' => &$this, 'row' => $row, 'infoArr' => $infoArr); foreach ($hookArr as $_funcRef) { $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } if ((string) $hookOut !== '') { $out .= $hookOut; } elseif (!empty($row['list_type'])) { $label = BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'list_type', $row['list_type']); if (!empty($label)) { $out .= $this->linkEditContent('<strong>' . $this->getLanguageService()->sL($label, true) . '</strong>', $row) . '<br />'; } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']); $out .= GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } elseif (!empty($row['select_key'])) { $out .= $this->getLanguageService()->sL(BackendUtility::getItemLabel('tt_content', 'select_key'), true) . ' ' . $row['select_key'] . '<br />'; } else { $out .= '<strong>' . $this->getLanguageService()->getLL('noPluginSelected') . '</strong>'; } $out .= $this->getLanguageService()->sL(BackendUtility::getLabelFromItemlist('tt_content', 'pages', $row['pages']), true) . '<br />'; break; default: $contentType = $this->CType_labels[$row['CType']]; if (isset($contentType)) { $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />'; if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } if ($row['image']) { $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'image'), $row) . '<br />'; } } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['CType']); $out .= GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } } // Wrap span-tags: $out = ' <span class="exampleContent">' . $out . '</span>'; // Add header: $out = $outHeader . $out; // Return values: if ($this->isDisabled('tt_content', $row)) { return '<span class="text-muted">' . $out . '</span>'; } else { return $out; } }
/** * Creates the table with the content columns * * @param array $lines Array with arrays of lines for each column * @param array $colPosArray Column position array * @param int $pid The id of the page * @return string HTML */ public function printRecordMap($lines, $colPosArray, $pid = 0) { $count = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(count($colPosArray), 1); $backendLayout = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getSelectedBackendLayout', $pid, $this); if (isset($backendLayout['__config']['backend_layout.'])) { $GLOBALS['LANG']->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf'); $table = '<div class="table-fit"><table class="table table-condensed table-bordered table-vertical-top">'; $colCount = (int) $backendLayout['__config']['backend_layout.']['colCount']; $rowCount = (int) $backendLayout['__config']['backend_layout.']['rowCount']; $table .= '<colgroup>'; for ($i = 0; $i < $colCount; $i++) { $table .= '<col style="width:' . 100 / $colCount . '%"></col>'; } $table .= '</colgroup>'; $table .= '<tbody>'; $tcaItems = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', $pid, $this); // Cycle through rows for ($row = 1; $row <= $rowCount; $row++) { $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.']; if (!isset($rowConfig)) { continue; } $table .= '<tr>'; for ($col = 1; $col <= $colCount; $col++) { $columnConfig = $rowConfig['columns.'][$col . '.']; if (!isset($columnConfig)) { continue; } // Which tt_content colPos should be displayed inside this cell $columnKey = (int) $columnConfig['colPos']; $head = ''; foreach ($tcaItems as $item) { if ($item[1] == $columnKey) { $head = $GLOBALS['LANG']->sL($item[0], TRUE); } } // Render the grid cell $table .= '<td' . (isset($columnConfig['colspan']) ? ' colspan="' . $columnConfig['colspan'] . '"' : '') . (isset($columnConfig['rowspan']) ? ' rowspan="' . $columnConfig['rowspan'] . '"' : '') . ' class="col-nowrap col-min' . (!isset($columnConfig['colPos']) ? ' warning' : '') . (isset($columnConfig['colPos']) && !$head ? ' danger' : '') . '">'; // Render header $table .= '<p>'; if (isset($columnConfig['colPos']) && $head) { $table .= '<strong>' . $this->wrapColumnHeader($head, '', '') . '</strong>'; } elseif ($columnConfig['colPos']) { $table .= '<em>' . $this->wrapColumnHeader($GLOBALS['LANG']->getLL('noAccess'), '', '') . '</em>'; } else { $table .= '<em>' . $this->wrapColumnHeader(($columnConfig['name'] ?: '') . ' (' . $GLOBALS['LANG']->getLL('notAssigned') . ')', '', '') . '</em>'; } $table .= '</p>'; // Render lines if (isset($columnConfig['colPos']) && $head && !empty($lines[$columnKey])) { $table .= '<ul class="list-unstyled">'; foreach ($lines[$columnKey] as $line) { $table .= '<li>' . $line . '</li>'; } $table .= '</ul>'; } $table .= '</td>'; } $table .= '</tr>'; } $table .= '</tbody>'; $table .= '</table></div>'; } else { // Traverse the columns here: $row = ''; foreach ($colPosArray as $kk => $vv) { $row .= '<td class="col-nowrap col-min" width="' . round(100 / $count) . '%">'; $row .= '<p><strong>' . $this->wrapColumnHeader($GLOBALS['LANG']->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $vv, $pid), TRUE), $vv) . '</strong></p>'; if (!empty($lines[$vv])) { $row .= '<ul class="list-unstyled">'; foreach ($lines[$vv] as $line) { $row .= '<li>' . $line . '</li>'; } $row .= '</ul>'; } $row .= '</td>'; } $table = ' <!-- Map of records in columns: --> <div class="table-fit"> <table class="table table-condensed table-bordered table-vertical-top"> <tr>' . $row . '</tr> </table> </div> '; } return $table; }
/** * @param $edit_record array * * @return array */ protected function makeQuickEditMenu($edit_record) { $lang = $this->getLanguageService(); $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $quickEditMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $quickEditMenu->setIdentifier('quickEditMenu'); $quickEditMenu->setLabel(''); // 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; } $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : ''; // Creating the selector box, allowing the user to select which element to edit: $isSelected = 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']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editLanguageHeader', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } else { $inValue = 'pages:' . $this->id; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editPageProperties', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // Selecting all content elements from this language and allowed colPos: $whereClause = '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'); if (!$this->getBackendUser()->user['admin']) { $whereClause .= ' AND editlock = 0'; } $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', $whereClause, '', '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']; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(' ')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), true) . ':__')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr); $quickEditMenu->addMenuItem($menuItem); } $inValue = 'tt_content:' . $cRow['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(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'])))->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); $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; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel', 1) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // If none is yet selected... if (!$isSelected) { $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__________')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $edit_record . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu); return $edit_record; }
/** * 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; }
/** * Draws the preview content for a content element * * @param string $row Content element * @param boolean $isRTE Set if the RTE link can be created. * @return string HTML * @throws \UnexpectedValueException * @todo Define visibility */ public function tt_content_drawItem($row, $isRTE = FALSE) { $out = ''; $outHeader = ''; // Make header: if ($row['header']) { $infoArr = array(); $this->getProcessedValue('tt_content', 'header_position,header_layout,header_link', $row, $infoArr); $hiddenHeaderNote = ''; // If header layout is set to 'hidden', display an accordant note: if ($row['header_layout'] == 100) { $hiddenHeaderNote = ' <em>[' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.hidden', TRUE) . ']</em>'; } $outHeader = $row['date'] ? htmlspecialchars($this->itemLabels['date'] . ' ' . BackendUtility::date($row['date'])) . '<br />' : ''; $outHeader .= '<strong>' . $this->linkEditContent($this->renderText($row['header']), $row) . $hiddenHeaderNote . '</strong><br />'; } // Make content: $infoArr = array(); $drawItem = TRUE; // Hook: Render an own preview of a record $drawItemHooks =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']; if (is_array($drawItemHooks)) { foreach ($drawItemHooks as $hookClass) { $hookObject = GeneralUtility::getUserObj($hookClass); if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) { throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\View\\PageLayoutViewDrawItemHookInterface', 1218547409); } $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row); } } // Draw preview of the item depending on its CType (if not disabled by previous hook): if ($drawItem) { switch ($row['CType']) { case 'header': if ($row['subheader']) { $out .= $this->linkEditContent($this->renderText($row['subheader']), $row) . '<br />'; } break; case 'text': case 'textpic': case 'image': if ($row['CType'] == 'text' || $row['CType'] == 'textpic') { if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } } if ($row['CType'] == 'textpic' || $row['CType'] == 'image') { if ($row['image']) { $out .= $this->thumbCode($row, 'tt_content', 'image') . '<br />'; if ($row['imagecaption']) { $out .= $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '<br />'; } } } break; case 'bullets': case 'table': case 'mailform': if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } break; case 'uploads': if ($row['media']) { $out .= $this->thumbCode($row, 'tt_content', 'media') . '<br />'; } break; case 'multimedia': if ($row['multimedia']) { $out .= $this->renderText($row['multimedia']) . '<br />'; $out .= $this->renderText($row['parameters']) . '<br />'; } break; case 'menu': if ($row['pages']) { $out .= $this->linkEditContent($row['pages'], $row) . '<br />'; } break; case 'shortcut': if (!empty($row['records'])) { $shortcutContent = array(); $recordList = explode(',', $row['records']); foreach ($recordList as $recordIdentifier) { $split = BackendUtility::splitTable_Uid($recordIdentifier); $tableName = empty($split[0]) ? 'tt_content' : $split[0]; $shortcutRecord = BackendUtility::getRecord($tableName, $split[1]); if (is_array($shortcutRecord)) { $icon = IconUtility::getSpriteIconForRecord($tableName, $shortcutRecord); $onClick = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon($icon, $tableName, $shortcutRecord['uid'], 1, '', '+copy,info,edit,view', TRUE); $shortcutContent[] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $icon . '</a>' . htmlspecialchars(BackendUtility::getRecordTitle($tableName, $shortcutRecord)); } } $out .= implode('<br />', $shortcutContent) . '<br />'; } break; case 'list': $hookArr = array(); $hookOut = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']]; } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT']; } if (count($hookArr) > 0) { $_params = array('pObj' => &$this, 'row' => $row, 'infoArr' => $infoArr); foreach ($hookArr as $_funcRef) { $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } if ((string) $hookOut !== '') { $out .= $hookOut; } elseif (!empty($row['list_type'])) { $label = BackendUtility::getLabelFromItemlist('tt_content', 'list_type', $row['list_type']); if (!empty($label)) { $out .= '<strong>' . $this->getLanguageService()->sL($label, TRUE) . '</strong><br />'; } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']); $out .= GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } elseif (!empty($row['select_key'])) { $out .= $this->getLanguageService()->sL(BackendUtility::getItemLabel('tt_content', 'select_key'), TRUE) . ' ' . $row['select_key'] . '<br />'; } else { $out .= '<strong>' . $this->getLanguageService()->getLL('noPluginSelected') . '</strong>'; } $out .= $this->getLanguageService()->sL(BackendUtility::getLabelFromItemlist('tt_content', 'pages', $row['pages']), TRUE) . '<br />'; break; case 'script': $out .= $this->getLanguageService()->sL(BackendUtility::getItemLabel('tt_content', 'select_key'), TRUE) . ' ' . $row['select_key'] . '<br />'; $out .= '<br />' . $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; $out .= '<br />' . $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '<br />'; break; default: $contentType = $this->CType_labels[$row['CType']]; if (isset($contentType)) { $out .= '<strong>' . htmlspecialchars($contentType) . '</strong><br />'; if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } if ($row['image']) { $out .= $this->thumbCode($row, 'tt_content', 'image') . '<br />'; } } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['CType']); $out .= GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } } // Wrap span-tags: $out = ' <span class="exampleContent">' . $out . '</span>'; // Add header: $out = $outHeader . $out; // Add RTE button: if ($isRTE) { $out .= $this->linkRTEbutton($row); } // Return values: if ($this->isDisabled('tt_content', $row)) { return $this->getDocumentTemplate()->dfw($out); } else { return $out; } }
/** * @test * @dataProvider getLabelFromItemlistReturnsCorrectFieldsDataProvider * * @param string $table * @param string $col * @param string $key * @param array $tca * @param string $expectedLabel */ public function getLabelFromItemlistReturnsCorrectFields($table, $col = '', $key = '', array $tca, $expectedLabel = '') { $GLOBALS['TCA'][$table] = $tca; $label = BackendUtility::getLabelFromItemlist($table, $col, $key); $this->assertEquals($label, $expectedLabel); }
/** * 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 table with the content columns * * @param array $lines Array with arrays of lines for each column * @param array $colPosArray Column position array * @param integer $pid The id of the page * @return string HTML * @todo Define visibility */ public function printRecordMap($lines, $colPosArray, $pid = 0) { $row1 = ''; $row2 = ''; $count = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(count($colPosArray), 1); $backendLayout = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getSelectedBackendLayout', $pid, $this); if (isset($backendLayout['__config']['backend_layout.'])) { $table = '<div class="t3-gridContainer"><table border="0" cellspacing="0" cellpadding="0" id="typo3-ttContentList">'; $colCount = (int) $backendLayout['__config']['backend_layout.']['colCount']; $rowCount = (int) $backendLayout['__config']['backend_layout.']['rowCount']; $table .= '<colgroup>'; for ($i = 0; $i < $colCount; $i++) { $table .= '<col style="width:' . 100 / $colCount . '%"></col>'; } $table .= '</colgroup>'; $tcaItems = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getColPosListItemsParsed', $pid, $this); // Cycle through rows for ($row = 1; $row <= $rowCount; $row++) { $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.']; if (!isset($rowConfig)) { continue; } $table .= '<tr>'; for ($col = 1; $col <= $colCount; $col++) { $columnConfig = $rowConfig['columns.'][$col . '.']; if (!isset($columnConfig)) { continue; } // Which tt_content colPos should be displayed inside this cell $columnKey = (int) $columnConfig['colPos']; $head = ''; foreach ($tcaItems as $item) { if ($item[1] == $columnKey) { $head = $GLOBALS['LANG']->sL($item[0], TRUE); } } // Render the grid cell $table .= '<td valign="top"' . (isset($columnConfig['colspan']) ? ' colspan="' . $columnConfig['colspan'] . '"' : '') . (isset($columnConfig['rowspan']) ? ' rowspan="' . $columnConfig['rowspan'] . '"' : '') . ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) ? ' t3-gridCell-unassigned' : '') . (isset($columnConfig['colPos']) && !$head ? ' t3-gridCell-restricted' : '') . (isset($columnConfig['colspan']) ? ' t3-gridCell-width' . $columnConfig['colspan'] : '') . (isset($columnConfig['rowspan']) ? ' t3-gridCell-height' . $columnConfig['rowspan'] : '') . '">'; $table .= '<div class="t3-page-colHeader t3-row-header">'; if (isset($columnConfig['colPos']) && $head) { $table .= $this->wrapColumnHeader($head, '', '') . '</div>' . implode('<br />', $lines[$columnKey]); } elseif ($columnConfig['colPos']) { $table .= $this->wrapColumnHeader($GLOBALS['LANG']->getLL('noAccess'), '', '') . '</div>'; } elseif ($columnConfig['name']) { $table .= $this->wrapColumnHeader($columnConfig['name'], '', '') . '</div>'; } else { $table .= $this->wrapColumnHeader($GLOBALS['LANG']->getLL('notAssigned'), '', '') . '</div>'; } $table .= '</td>'; } $table .= '</tr>'; } $table .= '</table></div>'; } else { // Traverse the columns here: foreach ($colPosArray as $kk => $vv) { $row1 .= '<td align="center" width="' . round(100 / $count) . '%"><div class="t3-page-colHeader t3-row-header">' . $this->wrapColumnHeader($GLOBALS['LANG']->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $vv, $pid), TRUE), $vv) . '</div></td>'; $row2 .= '<td valign="top" nowrap="nowrap">' . implode('<br />', $lines[$vv]) . '</td>'; } $table = ' <!-- Map of records in columns: --> <table border="0" cellpadding="0" cellspacing="0" id="typo3-ttContentList"> <tr>' . $row1 . '</tr> <tr>' . $row2 . '</tr> </table> '; } return $this->JSimgFunc('2') . $table; }
/** * @param $edit_record array * * @return array */ protected function makeQuickEditMenu($edit_record) { $lang = $this->getLanguageService(); $beUser = $this->getBackendUser(); $quickEditMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $quickEditMenu->setIdentifier('quickEditMenu'); $quickEditMenu->setLabel(''); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(['SET' => ['function' => 1]]); if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : ''; // Creating the selector box, allowing the user to select which element to edit: $isSelected = 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']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editLanguageHeader') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } else { $inValue = 'pages:' . $this->id; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editPageProperties') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); if ($this->MOD_SETTINGS['tt_content_showHidden']) { $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); } $queryBuilder->select('*')->from('tt_content')->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)), $queryBuilder->expr()->in('colPos', $queryBuilder->createNamedParameter(GeneralUtility::intExplode(',', $this->colPosList, true), Connection::PARAM_INT_ARRAY)), $queryBuilder->expr()->orX($queryBuilder->expr()->gte('t3ver_state', $queryBuilder->createNamedParameter((string) new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT)), $queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter((string) new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT))))->orderBy('colPos')->addOrderBy('sorting'); if (!$beUser->user['admin']) { $queryBuilder->andWhere($queryBuilder->expr()->eq('editlock', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))); } $statement = $queryBuilder->execute(); $colPos = null; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $statement->fetch()) { 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']; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(' ')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos)) . ':__')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr); $quickEditMenu->addMenuItem($menuItem); } $inValue = 'tt_content:' . $cRow['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $beUser->uc['titleLen']))->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); $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; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // If none is yet selected... if (!$isSelected) { $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__________')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $edit_record . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu); return $edit_record; }