/** * Enrich the processed record information with the resolved title * * @param array $result Incoming result array * @return array Modified array */ public function addData(array $result) { if (!isset($result['processedTca']['ctrl']['label'])) { throw new \UnexpectedValueException('TCA of table ' . $result['tableName'] . ' misses required [\'ctrl\'][\'label\'] definition.', 1443706103); } if ($result['isInlineChild'] && isset($result['processedTca']['ctrl']['formattedLabel_userFunc'])) { // inline child with formatted user func is first $parameters = ['table' => $result['tableName'], 'row' => $result['databaseRow'], 'title' => '', 'isOnSymmetricSide' => $result['isOnSymmetricSide'], 'options' => isset($result['processedTca']['ctrl']['formattedLabel_userFunc_options']) ? $result['processedTca']['ctrl']['formattedLabel_userFunc_options'] : [], 'parent' => ['uid' => $result['databaseRow']['uid'], 'config' => $result['inlineParentConfig']]]; // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = null; GeneralUtility::callUserFunction($result['processedTca']['ctrl']['formattedLabel_userFunc'], $parameters, $null); $result['recordTitle'] = $parameters['title']; } elseif ($result['isInlineChild'] && (isset($result['inlineParentConfig']['foreign_label']) || isset($result['inlineParentConfig']['symmetric_label']))) { // inline child with foreign label or symmetric inline child with symmetric_label $fieldName = $result['isOnSymmetricSide'] ? $result['inlineParentConfig']['symmetric_label'] : $result['inlineParentConfig']['foreign_label']; // @todo: this is a mixup here. problem is the prep method cuts the string, but also hsc's the thing. // @todo: this is uncool for the userfuncs, so it is applied only here. however, the OuterWrapContainer // @todo: also prep()'s the title created by the else patch below ... find a better separation and clean this up! $result['recordTitle'] = BackendUtility::getRecordTitlePrep($this->getRecordTitleForField($fieldName, $result)); } elseif (isset($result['processedTca']['ctrl']['label_userFunc'])) { // userFunc takes precedence over everything else $parameters = ['table' => $result['tableName'], 'row' => $result['databaseRow'], 'title' => '', 'options' => isset($result['processedTca']['ctrl']['label_userFunc_options']) ? $result['processedTca']['ctrl']['label_userFunc_options'] : []]; $null = null; GeneralUtility::callUserFunction($result['processedTca']['ctrl']['label_userFunc'], $parameters, $null); $result['recordTitle'] = $parameters['title']; } else { // standard record $result = $this->getRecordTitleByLabelProperties($result); } return $result; }
/** * Get the user function label for the file_reference table * * @param array $params * @return void */ public function getInlineLabel(array &$params) { $sysFileFields = isset($params['options']['sys_file']) && is_array($params['options']['sys_file']) ? $params['options']['sys_file'] : []; if (empty($sysFileFields)) { // Nothing to do $params['title'] = $params['row']['uid']; return; } // In case of a group field uid_local has the table_uid|label syntax $tableAndUid = array_shift(GeneralUtility::trimExplode('|', $params['row']['uid_local'], true, 2)); $fileInfo = BackendUtility::splitTable_Uid($tableAndUid); $fileRecord = BackendUtility::getRecord($fileInfo[0], $fileInfo[1]); // Configuration $title = []; foreach ($sysFileFields as $field) { $value = ''; if ($field === 'title') { if (isset($params['row']['title'])) { $fullTitle = $params['row']['title']; } else { try { $metaDataRepository = GeneralUtility::makeInstance(MetaDataRepository::class); $metaData = $metaDataRepository->findByFileUid($fileRecord['uid']); $fullTitle = $metaData['title']; } catch (InvalidUidException $e) { /** * We just catch the exception here * Reasoning: There is nothing an editor or even admin could do */ $fullTitle = ''; } } $value = BackendUtility::getRecordTitlePrep(htmlspecialchars($fullTitle)); } else { if (isset($params['row'][$field])) { $value = htmlspecialchars($params['row'][$field]); } elseif (isset($fileRecord[$field])) { $value = BackendUtility::getRecordTitlePrep($fileRecord[$field]); } } if ((string) $value === '') { continue; } $labelText = LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_file.' . $field, 'lang'); $title[] = '<dt>' . htmlspecialchars($labelText) . '</dt>' . '<dd>' . $value . '</dd>'; } $params['title'] = '<dl>' . implode('', $title) . '</dl>'; }
/** * Returns the title (based on $code) of a record (from table $table) with the proper link around (that is for "pages"-records a link to the level of that record...) * * @param string $table Table name * @param int $uid UID (not used here) * @param string $code Title string * @param array $row Records array (from table name) * @return string */ public function linkWrapItems($table, $uid, $code, $row) { if (!$code) { $code = '<i>[' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title')) . ']</i>'; } else { $code = BackendUtility::getRecordTitlePrep($code, $this->fixedL); } $title = BackendUtility::getRecordTitle($table, $row, false, true); $ficon = $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render(); $ATag = '<a href="#" data-close="0" title="' . htmlspecialchars($this->getLanguageService()->getLL('addToList')) . '">'; $ATag_alt = '<a href="#" data-close="1" title="' . htmlspecialchars($this->getLanguageService()->getLL('addToList')) . '">'; $ATag_e = '</a>'; $out = '<span data-uid="' . htmlspecialchars($row['uid']) . '" data-table="' . htmlspecialchars($table) . '" data-title="' . htmlspecialchars($title) . '" data-icon="' . htmlspecialchars($ficon) . '">'; $out .= $ATag . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . $ATag_e . $ATag_alt . $code . $ATag_e; $out .= '</span>'; return $out; }
/** * Get the user function label for the file_reference table * * @param array $params * @return void */ public function getInlineLabel(array &$params) { $sysFileFields = isset($params['options']['sys_file']) && is_array($params['options']['sys_file']) ? $params['options']['sys_file'] : array(); if (!count($sysFileFields)) { // Nothing to do $params['title'] = $params['row']['uid']; return; } $fileInfo = BackendUtility::splitTable_Uid($params['row']['uid_local'], 2); $fileRecord = BackendUtility::getRecord($fileInfo[0], $fileInfo[1]); // Configuration $title = array(); foreach ($sysFileFields as $field) { $value = ''; if ($field === 'title') { if (isset($params['row']['title'])) { $fullTitle = $params['row']['title']; } else { try { $metaDataRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository'); $metaData = $metaDataRepository->findByFileUid($fileRecord['uid']); $fullTitle = $metaData['title']; } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidUidException $e) { /** * We just catch the exception here * Reasoning: There is nothing an editor or even admin could do */ } } $value = BackendUtility::getRecordTitlePrep(htmlspecialchars($fullTitle)); } else { if (isset($params['row'][$field])) { $value = htmlspecialchars($params['row'][$field]); } elseif (isset($fileRecord[$field])) { $value = BackendUtility::getRecordTitlePrep($fileRecord[$field]); } } if (!strlen($value)) { continue; } $labelText = LocalizationUtility::translate('LLL:EXT:lang/locallang_tca.xlf:sys_file.' . $field, 'lang'); $title[] = '<dt>' . htmlspecialchars($labelText) . '</dt>' . '<dd>' . $value . '</dd>'; } $params['title'] = '<dl>' . implode('', $title) . '</dl>'; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $thumbnail = FALSE; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing was successful. if (!$processedImage->usesOriginalFile()) { $imageUrl = $processedImage->getPublicUrl(TRUE); $thumbnail = '<img class="t3-form-field-header-inline-thumbnail-image" src="' . $imageUrl . '" alt="' . htmlspecialchars($altText) . '" title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $headerClasses = ' t3-form-field-header-inline-has-thumbnail'; $mediaContainer = '<div class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $headerClasses = ' t3-form-field-header-inline-has-icon'; $mediaContainer = '<div class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = '<div class="t3-form-field-header-inline-wrap' . $headerClasses . '">' . '<div class="t3-form-field-header-inline-ctrl">' . $ctrl . '</div>' . '<div class="t3-form-field-header-inline-body">' . $mediaContainer . '<div class="t3-form-field-header-inline-summary">' . $label . '</div>' . '</div>' . '</div>'; return $header; }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $languageService = $this->getLanguageService(); $backendUser = $this->getBackendUserAuthentication(); $table = $this->data['tableName']; $row = $this->data['databaseRow']; $options = $this->data; if (empty($this->data['fieldListToRender'])) { $options['renderType'] = 'fullRecordContainer'; } else { $options['renderType'] = 'listOfFieldsContainer'; } $result = $this->nodeFactory->create($options)->render(); $childHtml = $result['html']; $recordPath = ''; // @todo: what is this >= 0 check for? wsol cases?! if ($this->data['effectivePid'] >= 0) { $permissionsClause = $backendUser->getPagePermsClause(1); $recordPath = BackendUtility::getRecordPath($this->data['effectivePid'], $permissionsClause, 15); } $iconFactory = GeneralUtility::makeInstance(IconFactory::class); $icon = '<span title="' . htmlspecialchars($recordPath) . '">' . $iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>'; // @todo: Could this be done in a more clever way? Does it work at all? $tableTitle = $languageService->sL($this->data['processedTca']['ctrl']['title']); if ($this->data['command'] === 'new') { $newOrUid = ' <span class="typo3-TCEforms-newToken">' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.new', true) . '</span>'; // @todo: There is quite some stuff do to for WS overlays ... $workspacedPageRecord = BackendUtility::getRecordWSOL('pages', $this->data['effectivePid'], 'title'); $pageTitle = BackendUtility::getRecordTitle('pages', $workspacedPageRecord, true, false); if ($table === 'pages') { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewPage', true); $pageTitle = sprintf($label, $tableTitle); } else { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewRecord', true); if ($this->data['effectivePid'] === 0) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewRecordRootLevel', true); } $pageTitle = sprintf($label, $tableTitle, $pageTitle); } } else { $icon = BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid'], 1, '', '+copy,info,edit,view'); $newOrUid = ' <span class="typo3-TCEforms-recUid">[' . htmlspecialchars($row['uid']) . ']</span>'; // @todo: getRecordTitlePrep applies an htmlspecialchars here $recordLabel = BackendUtility::getRecordTitlePrep($this->data['recordTitle']); if ($table === 'pages') { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editPage', true); $pageTitle = sprintf($label, $tableTitle, $recordLabel); } else { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecord', true); $workspacedPageRecord = BackendUtility::getRecordWSOL('pages', $row['pid'], 'uid,title'); $pageTitle = BackendUtility::getRecordTitle('pages', $workspacedPageRecord, true, false); if (empty($recordLabel)) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecordNoTitle', true); } if ($this->data['effectivePid'] === 0) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecordRootLevel', true); } if (!empty($recordLabel)) { // Use record title and prepend an edit label. $pageTitle = sprintf($label, $tableTitle, $recordLabel, $pageTitle); } else { // Leave out the record title since it is not set. $pageTitle = sprintf($label, $tableTitle, $pageTitle); } } } $view = GeneralUtility::makeInstance(StandaloneView::class); $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/OuterWrapContainer.html')); $descriptionColumn = !empty($this->data['processedTca']['ctrl']['descriptionColumn']) ? $this->data['processedTca']['ctrl']['descriptionColumn'] : null; if ($descriptionColumn !== null) { $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.recordInformation'); $content = $this->data['databaseRow'][$descriptionColumn]; $view->assignMultiple(['infoBoxMessageTitle' => $title, 'infoBoxMessage' => $content]); } $view->assignMultiple(array('pageTitle' => $pageTitle, 'childHtml' => $childHtml, 'icon' => $icon, 'tableTitle' => $tableTitle, 'newOrUid' => $newOrUid)); $result['html'] = $view->render(); return $result; }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $languageService = $this->getLanguageService(); $backendUser = $this->getBackendUserAuthentication(); $table = $this->data['tableName']; $row = $this->data['databaseRow']; $options = $this->data; if (empty($this->data['fieldListToRender'])) { $options['renderType'] = 'fullRecordContainer'; } else { $options['renderType'] = 'listOfFieldsContainer'; } $result = $this->nodeFactory->create($options)->render(); $childHtml = $result['html']; $recordPath = ''; // @todo: what is this >= 0 check for? wsol cases?! if ($this->data['effectivePid'] >= 0) { $permissionsClause = $backendUser->getPagePermsClause(1); $recordPath = BackendUtility::getRecordPath($this->data['effectivePid'], $permissionsClause, 15); } $iconFactory = GeneralUtility::makeInstance(IconFactory::class); $icon = '<span title="' . htmlspecialchars($recordPath) . '">' . $iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>'; // @todo: Could this be done in a more clever way? Does it work at all? $tableTitle = $languageService->sL($this->data['processedTca']['ctrl']['title']); if ($this->data['command'] === 'new') { $newOrUid = ' <span class="typo3-TCEforms-newToken">' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.new', true) . '</span>'; // @todo: There is quite some stuff do to for WS overlays ... $workspacedPageRecord = BackendUtility::getRecordWSOL('pages', $this->data['effectivePid'], 'title'); $pageTitle = BackendUtility::getRecordTitle('pages', $workspacedPageRecord, true, false); if ($table === 'pages') { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewPage', true); $pageTitle = sprintf($label, $tableTitle); } else { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewRecord', true); if ($this->data['effectivePid'] === 0) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.createNewRecordRootLevel', true); } $pageTitle = sprintf($label, $tableTitle, $pageTitle); } } else { $icon = BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid'], 1, '', '+copy,info,edit,view'); $newOrUid = ' <span class="typo3-TCEforms-recUid">[' . htmlspecialchars($row['uid']) . ']</span>'; // @todo: getRecordTitlePrep applies an htmlspecialchars here $recordLabel = BackendUtility::getRecordTitlePrep($this->data['recordTitle']); if ($table === 'pages') { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editPage', true); $pageTitle = sprintf($label, $tableTitle, $recordLabel); } else { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecord', true); $workspacedPageRecord = BackendUtility::getRecordWSOL('pages', $row['pid'], 'uid,title'); $pageTitle = BackendUtility::getRecordTitle('pages', $workspacedPageRecord, true, false); if (empty($recordLabel)) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecordNoTitle', true); } if ($this->data['effectivePid'] === 0) { $label = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.editRecordRootLevel', true); } if (!empty($recordLabel)) { // Use record title and prepend an edit label. $pageTitle = sprintf($label, $tableTitle, $recordLabel, $pageTitle); } else { // Leave out the record title since it is not set. $pageTitle = sprintf($label, $tableTitle, $pageTitle); } } } $html = array(); $html[] = '<h1>' . $pageTitle . '</h1>'; $html[] = '<div class="typo3-TCEforms">'; $html[] = $childHtml; $html[] = '<div class="help-block text-right">'; $html[] = $icon . ' <strong>' . htmlspecialchars($tableTitle) . '</strong>' . ' ' . $newOrUid; $html[] = '</div>'; $html[] = '</div>'; $result['html'] = implode(LF, $html); return $result; }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $backendUser = $this->getBackendUserAuthentication(); $languageService = $this->getLanguageService(); $resultArray = $this->initializeResultArray(); $table = $this->data['tableName']; $row = $this->data['databaseRow']; $fieldName = $this->data['fieldName']; // @todo: it should be safe at this point, this array exists ... if (!is_array($this->data['processedTca']['columns'][$fieldName])) { return $resultArray; } $parameterArray = array(); $parameterArray['fieldConf'] = $this->data['processedTca']['columns'][$fieldName]; $isOverlay = false; // This field decides whether the current record is an overlay (as opposed to being a standalone record) // Based on this decision we need to trigger field exclusion or special rendering (like readOnly) if (isset($this->data['processedTca']['ctrl']['transOrigPointerField']) && is_array($this->data['processedTca']['columns'][$this->data['processedTca']['ctrl']['transOrigPointerField']]) && is_array($row[$this->data['processedTca']['ctrl']['transOrigPointerField']]) && $row[$this->data['processedTca']['ctrl']['transOrigPointerField']][0] > 0) { $isOverlay = true; } // A couple of early returns in case the field should not be rendered // Check if this field is configured and editable according to exclude fields and other configuration if ($parameterArray['fieldConf']['exclude'] && !$backendUser->check('non_exclude_fields', $table . ':' . $fieldName) || $parameterArray['fieldConf']['config']['type'] === 'passthrough' || !$backendUser->isRTE() && $parameterArray['fieldConf']['config']['showIfRTE'] || $isOverlay && !$parameterArray['fieldConf']['l10n_display'] && $parameterArray['fieldConf']['l10n_mode'] === 'exclude' || $isOverlay && $this->data['localizationMode'] && $this->data['localizationMode'] !== $parameterArray['fieldConf']['l10n_cat'] || $this->inlineFieldShouldBeSkipped()) { return $resultArray; } $parameterArray['fieldTSConfig'] = []; if (isset($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']) && is_array($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'])) { $parameterArray['fieldTSConfig'] = $this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']; } if ($parameterArray['fieldTSConfig']['disabled']) { return $resultArray; } // Override fieldConf by fieldTSconfig: $parameterArray['fieldConf']['config'] = FormEngineUtility::overrideFieldConf($parameterArray['fieldConf']['config'], $parameterArray['fieldTSConfig']); $parameterArray['itemFormElName'] = 'data[' . $table . '][' . $row['uid'] . '][' . $fieldName . ']'; $parameterArray['itemFormElID'] = 'data_' . $table . '_' . $row['uid'] . '_' . $fieldName; $newElementBaseName = $this->data['elementBaseName'] . '[' . $table . '][' . $row['uid'] . '][' . $fieldName . ']'; // The value to show in the form field. $parameterArray['itemFormElValue'] = $row[$fieldName]; // Set field to read-only if configured for translated records to show default language content as readonly if ($parameterArray['fieldConf']['l10n_display'] && GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'], 'defaultAsReadonly') && $isOverlay) { $parameterArray['fieldConf']['config']['readOnly'] = true; $parameterArray['itemFormElValue'] = $this->data['defaultLanguageRow'][$fieldName]; } if (strpos($this->data['processedTca']['ctrl']['type'], ':') === false) { $typeField = $this->data['processedTca']['ctrl']['type']; } else { $typeField = substr($this->data['processedTca']['ctrl']['type'], 0, strpos($this->data['processedTca']['ctrl']['type'], ':')); } // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. // This is used for eg. "type" fields and others configured with "requestUpdate" if (!empty($this->data['processedTca']['ctrl']['type']) && $fieldName === $typeField || !empty($this->data['processedTca']['ctrl']['requestUpdate']) && GeneralUtility::inList(str_replace(' ', '', $this->data['processedTca']['ctrl']['requestUpdate']), $fieldName)) { if ($backendUser->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { $alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });'; } else { $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };'; } } else { $alertMsgOnChange = ''; } // JavaScript code for event handlers: $parameterArray['fieldChangeFunc'] = array(); $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged(' . GeneralUtility::quoteJSvalue($table) . ',' . GeneralUtility::quoteJSvalue($row['uid']) . ',' . GeneralUtility::quoteJSvalue($fieldName) . ',' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ');'; $parameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange; // If this is the child of an inline type and it is the field creating the label if ($this->isInlineChildAndLabelField($table, $fieldName)) { /** @var InlineStackProcessor $inlineStackProcessor */ $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class); $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']); $inlineDomObjectId = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']); $inlineObjectId = implode('-', array($inlineDomObjectId, $table, $row['uid'])); $parameterArray['fieldChangeFunc']['inline'] = 'inline.handleChangedField(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ',' . GeneralUtility::quoteJSvalue($inlineObjectId) . ');'; } // Based on the type of the item, call a render function on a child element $options = $this->data; $options['parameterArray'] = $parameterArray; $options['elementBaseName'] = $newElementBaseName; if (!empty($parameterArray['fieldConf']['config']['renderType'])) { $options['renderType'] = $parameterArray['fieldConf']['config']['renderType']; } else { // Fallback to type if no renderType is given $options['renderType'] = $parameterArray['fieldConf']['config']['type']; } $resultArray = $this->nodeFactory->create($options)->render(); // If output is empty stop further processing. // This means there was internal processing only and we don't need to add additional information if (empty($resultArray['html'])) { return $resultArray; } $html = $resultArray['html']; // @todo: the language handling, the null and the placeholder stuff should be embedded in the single // @todo: element classes. Basically, this method should return here and have the element classes // @todo: decide on language stuff and other wraps already. // Add language + diff $renderLanguageDiff = true; if ($parameterArray['fieldConf']['l10n_display'] && (GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'], 'hideDiff') || GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'], 'defaultAsReadonly'))) { $renderLanguageDiff = false; } if ($renderLanguageDiff) { $html = $this->renderDefaultLanguageContent($table, $fieldName, $row, $html); $html = $this->renderDefaultLanguageDiff($table, $fieldName, $row, $html); } $fieldItemClasses = array('t3js-formengine-field-item'); // NULL value and placeholder handling $nullControlNameAttribute = ' name="' . htmlspecialchars('control[active][' . $table . '][' . $row['uid'] . '][' . $fieldName . ']') . '"'; if (!empty($parameterArray['fieldConf']['config']['eval']) && GeneralUtility::inList($parameterArray['fieldConf']['config']['eval'], 'null') && (empty($parameterArray['fieldConf']['config']['mode']) || $parameterArray['fieldConf']['config']['mode'] !== 'useOrOverridePlaceholder')) { // This field has eval=null set, but has no useOverridePlaceholder defined. // Goal is to have a field that can distinct between NULL and empty string in the database. // A checkbox and an additional hidden field will be created, both with the same name // and prefixed with "control[active]". If the checkbox is set (value 1), the value from the casual // input field will be written to the database. If the checkbox is not set, the hidden field // transfers value=0 to DataHandler, the value of the input field will then be reset to NULL by the // DataHandler at an early point in processing, so NULL will be written to DB as field value. // If the value of the field *is* NULL at the moment, an additional class is set // @todo: This does not work well at the moment, but is kept for now. see input_14 of ext:styleguide as example $checked = ' checked="checked"'; if ($this->data['databaseRow'][$fieldName] === null) { $fieldItemClasses[] = 'disabled'; $checked = ''; } $formElementName = 'data[' . $table . '][' . $row['uid'] . '][' . $fieldName . ']'; $onChange = htmlspecialchars('typo3form.fieldSetNull(' . GeneralUtility::quoteJSvalue($formElementName) . ', !this.checked)'); $nullValueWrap = array(); $nullValueWrap[] = '<div class="' . implode(' ', $fieldItemClasses) . '">'; $nullValueWrap[] = '<div class="t3-form-field-disable"></div>'; $nullValueWrap[] = '<div class="checkbox">'; $nullValueWrap[] = '<label>'; $nullValueWrap[] = '<input type="hidden"' . $nullControlNameAttribute . ' value="0" />'; $nullValueWrap[] = '<input type="checkbox"' . $nullControlNameAttribute . ' value="1" onchange="' . $onChange . '"' . $checked . ' /> '; $nullValueWrap[] = '</label>'; $nullValueWrap[] = $html; $nullValueWrap[] = '</div>'; $nullValueWrap[] = '</div>'; $html = implode(LF, $nullValueWrap); } elseif (isset($parameterArray['fieldConf']['config']['mode']) && $parameterArray['fieldConf']['config']['mode'] === 'useOrOverridePlaceholder') { // This field has useOverridePlaceholder set. // Here, a value from a deeper DB structure can be "fetched up" as value, and can also be overridden by a // local value. This is used in FAL, where eg. the "title" field can have the default value from sys_file_metadata, // the title field of sys_file_reference is then set to NULL. Or the "override" checkbox is set, and a string // or an empty string is then written to the field of sys_file_reference. // The situation is similar to the NULL handling above, but additionally a "default" value should be shown. // To achieve this, again a hidden control[hidden] field is added together with a checkbox with the same name // to transfer the information whether the default value should be used or not: Checkbox checked transfers 1 as // value in control[active], meaning the overridden value should be used. // Additionally to the casual input field, a second field is added containing the "placeholder" value. This // field has no name attribute and is not transferred at all. Those two are then hidden / shown depending // on the state of the above checkbox in via JS. $placeholder = empty($parameterArray['fieldConf']['config']['placeholder']) ? '' : $parameterArray['fieldConf']['config']['placeholder']; $onChange = 'typo3form.fieldTogglePlaceholder(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', !this.checked)'; $checked = $parameterArray['itemFormElValue'] === null ? '' : ' checked="checked"'; $resultArray['additionalJavaScriptPost'][] = 'typo3form.fieldTogglePlaceholder(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', ' . ($checked ? 'false' : 'true') . ');'; // Renders an input or textarea field depending on type of "parent" $options = array(); $options['databaseRow'] = array(); $options['table'] = ''; $options['parameterArray'] = $parameterArray; $options['parameterArray']['itemFormElValue'] = GeneralUtility::fixed_lgd_cs($placeholder, 30); $options['renderType'] = 'none'; $noneElementResult = $this->nodeFactory->create($options)->render(); $noneElementHtml = $noneElementResult['html']; $placeholderWrap = array(); $placeholderWrap[] = '<div class="' . implode(' ', $fieldItemClasses) . '">'; $placeholderWrap[] = '<div class="t3-form-field-disable"></div>'; $placeholderWrap[] = '<div class="checkbox">'; $placeholderWrap[] = '<label>'; $placeholderWrap[] = '<input type="hidden"' . $nullControlNameAttribute . ' value="0" />'; $placeholderWrap[] = '<input type="checkbox"' . $nullControlNameAttribute . ' value="1" id="tce-forms-textfield-use-override-' . $fieldName . '-' . $row['uid'] . '" onchange="' . htmlspecialchars($onChange) . '"' . $checked . ' />'; $placeholderWrap[] = sprintf($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.placeholder.override'), BackendUtility::getRecordTitlePrep($placeholder, 20)); $placeholderWrap[] = '</label>'; $placeholderWrap[] = '</div>'; $placeholderWrap[] = '<div class="t3js-formengine-placeholder-placeholder">'; $placeholderWrap[] = $noneElementHtml; $placeholderWrap[] = '</div>'; $placeholderWrap[] = '<div class="t3js-formengine-placeholder-formfield">'; $placeholderWrap[] = $html; $placeholderWrap[] = '</div>'; $placeholderWrap[] = '</div>'; $html = implode(LF, $placeholderWrap); } elseif ($parameterArray['fieldConf']['config']['type'] !== 'user' || empty($parameterArray['fieldConf']['config']['noTableWrapping'])) { // Add a casual wrap if the field is not of type user with no wrap requested. $standardWrap = array(); $standardWrap[] = '<div class="' . implode(' ', $fieldItemClasses) . '">'; $standardWrap[] = '<div class="t3-form-field-disable"></div>'; $standardWrap[] = $html; $standardWrap[] = '</div>'; $html = implode(LF, $standardWrap); } $resultArray['html'] = $html; return $resultArray; }
/** * Returns the form HTML code for a database table field. * * @param string $table The table name * @param string $field The field name * @param array $row The record to edit from the database table. * @param string $altName Alternative field name label to show. * @param boolean $palette Set this if the field is on a palette (in top frame), otherwise not. (if set, field will render as a hidden field). * @param string $extra The "extra" options from "Part 4" of the field configurations found in the "types" "showitem" list. Typically parsed by $this->getSpecConfFromString() in order to get the options as an associative array. * @param integer $pal The palette pointer. * @return mixed String (normal) or array (palettes) * @todo Define visibility */ public function getSingleField($table, $field, $row, $altName = '', $palette = FALSE, $extra = '', $pal = 0) { // Hook: getSingleField_preProcess foreach ($this->hookObjectsSingleField as $hookObj) { if (method_exists($hookObj, 'getSingleField_preProcess')) { $hookObj->getSingleField_preProcess($table, $field, $row, $altName, $palette, $extra, $pal, $this); } } $out = ''; $PA = array(); $PA['altName'] = $altName; $PA['palette'] = $palette; $PA['extra'] = $extra; $PA['pal'] = $pal; // Get the TCA configuration for the current field: $PA['fieldConf'] = $GLOBALS['TCA'][$table]['columns'][$field]; $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ?: $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']); // Evaluate display condition $displayConditionResult = TRUE; if (is_array($PA['fieldConf']) && $PA['fieldConf']['displayCond'] && is_array($row)) { /** @var $elementConditionMatcher \TYPO3\CMS\Backend\Form\ElementConditionMatcher */ $elementConditionMatcher = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\ElementConditionMatcher'); $displayConditionResult = $elementConditionMatcher->match($PA['fieldConf']['displayCond'], $row); } // Check if this field is configured and editable (according to excludefields + other configuration) if (is_array($PA['fieldConf']) && !$skipThisField && (!$PA['fieldConf']['exclude'] || $this->getBackendUserAuthentication()->check('non_exclude_fields', $table . ':' . $field)) && $PA['fieldConf']['config']['form_type'] != 'passthrough' && ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE']) && $displayConditionResult && (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || $PA['fieldConf']['l10n_mode'] !== 'exclude' || $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] <= 0) && (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || !$this->localizationMode || $this->localizationMode === $PA['fieldConf']['l10n_cat'])) { // Fetching the TSconfig for the current table/field. This includes the $row which means that $PA['fieldTSConfig'] = $this->setTSconfig($table, $row, $field); // If the field is NOT disabled from TSconfig (which it could have been) then render it if (!$PA['fieldTSConfig']['disabled']) { // Override fieldConf by fieldTSconfig: $PA['fieldConf']['config'] = $this->overrideFieldConf($PA['fieldConf']['config'], $PA['fieldTSConfig']); // Init variables: $PA['itemFormElName'] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name, in case of file uploads $PA['itemFormElName_file'] = $this->prependFormFieldNames_file . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name, to activate elements // If the "eval" list contains "null", elements can be deactivated which results in storing NULL to database $PA['itemFormElNameActive'] = $this->prependFormFieldNamesActive . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // The value to show in the form field. $PA['itemFormElValue'] = $row[$field]; $PA['itemFormElID'] = $this->prependFormFieldNames . '_' . $table . '_' . $row['uid'] . '_' . $field; // Set field to read-only if configured for translated records to show default language content as readonly if ($PA['fieldConf']['l10n_display'] && GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly') && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) { $PA['fieldConf']['config']['readOnly'] = TRUE; $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field]; } if (strpos($GLOBALS['TCA'][$table]['ctrl']['type'], ':') === FALSE) { $typeField = $GLOBALS['TCA'][$table]['ctrl']['type']; } else { $typeField = substr($GLOBALS['TCA'][$table]['ctrl']['type'], 0, strpos($GLOBALS['TCA'][$table]['ctrl']['type'], ':')); } // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. This is used for eg. "type" fields and others configured with "requestUpdate" if (!empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $field === $typeField || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList(str_replace(' ', '', $GLOBALS['TCA'][$table]['ctrl']['requestUpdate']), $field)) { if ($this->getBackendUserAuthentication()->jsConfirmation(1)) { $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };'; } else { $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };'; } } else { $alertMsgOnChange = ''; } // Render as a hidden field? if (in_array($field, $this->hiddenFieldListArr)) { $this->hiddenFieldAccum[] = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />'; } else { // Render as a normal field: // If the field is NOT a palette field, then we might create an icon which links to a palette for the field, if one exists. $palJSfunc = ''; $thePalIcon = ''; if (!$PA['palette']) { $paletteFields = $this->loadPaletteElements($table, $row, $PA['pal']); if ($PA['pal'] && $this->isPalettesCollapsed($table, $PA['pal']) && count($paletteFields)) { list($thePalIcon, $palJSfunc) = $this->wrapOpenPalette(IconUtility::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1); } } // onFocus attribute to add to the field: $PA['onFocus'] = $palJSfunc && !$this->getBackendUserAuthentication()->uc['dontShowPalettesOnFocusInAB'] ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"' : ''; $PA['label'] = $PA['altName'] ?: $PA['fieldConf']['label']; $PA['label'] = $PA['fieldTSConfig']['label'] ?: $PA['label']; $PA['label'] = $PA['fieldTSConfig']['label.'][$this->getLanguageService()->lang] ?: $PA['label']; $PA['label'] = $this->sL($PA['label']); // JavaScript code for event handlers: $PA['fieldChangeFunc'] = array(); $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged(\'' . $table . '\',\'' . $row['uid'] . '\',\'' . $field . '\',\'' . $PA['itemFormElName'] . '\');'; $PA['fieldChangeFunc']['alert'] = $alertMsgOnChange; // If this is the child of an inline type and it is the field creating the label if ($this->inline->isInlineChildAndLabelField($table, $field)) { $inlineObjectId = implode(InlineElement::Structure_Separator, array($this->inline->inlineNames['object'], $table, $row['uid'])); $PA['fieldChangeFunc']['inline'] = 'inline.handleChangedField(\'' . $PA['itemFormElName'] . '\',\'' . $inlineObjectId . '\');'; } // Based on the type of the item, call a render function: $item = $this->getSingleField_SW($table, $field, $row, $PA); // Add language + diff if ($PA['fieldConf']['l10n_display'] && (GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly'))) { $renderLanguageDiff = FALSE; } else { $renderLanguageDiff = TRUE; } if ($renderLanguageDiff) { $item = $this->renderDefaultLanguageContent($table, $field, $row, $item); $item = $this->renderDefaultLanguageDiff($table, $field, $row, $item); } // If the record has been saved and the "linkTitleToSelf" is set, we make the field name into a link, which will load ONLY this field in alt_doc.php $label = htmlspecialchars($PA['label'], ENT_COMPAT, 'UTF-8', FALSE); if (MathUtility::canBeInterpretedAsInteger($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !GeneralUtility::_GP('columnsOnly')) { $lTTS_url = $this->backPath . 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl()); $label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>'; } if (isset($PA['fieldConf']['config']['mode']) && $PA['fieldConf']['config']['mode'] == 'useOrOverridePlaceholder') { $placeholder = $this->getPlaceholderValue($table, $field, $PA['fieldConf']['config'], $row); $onChange = 'typo3form.fieldTogglePlaceholder(' . GeneralUtility::quoteJSvalue($PA['itemFormElName']) . ', !this.checked)'; $checked = $PA['itemFormElValue'] === NULL ? '' : ' checked="checked"'; $this->additionalJS_post[] = 'typo3form.fieldTogglePlaceholder(' . GeneralUtility::quoteJSvalue($PA['itemFormElName']) . ', ' . ($checked ? 'false' : 'true') . ');'; $item = '<div class="t3-form-field-placeholder-override">' . '<span class="t3-tceforms-placeholder-override-checkbox">' . '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElNameActive']) . '" value="0" />' . '<input type="checkbox" name="' . htmlspecialchars($PA['itemFormElNameActive']) . '" value="1" id="tce-forms-textfield-use-override-' . $field . '-' . $row['uid'] . '" onchange="' . htmlspecialchars($onChange) . '"' . $checked . ' />' . '<label for="tce-forms-textfield-use-override-' . $field . '-' . $row['uid'] . '">' . sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.placeholder.override'), BackendUtility::getRecordTitlePrep($placeholder, 20)) . '</label>' . '</span>' . '<div class="t3-form-placeholder-placeholder">' . $this->getSingleField_typeNone_render($PA['fieldConf']['config'], GeneralUtility::fixed_lgd_cs($placeholder, 30)) . '</div>' . '<div class="t3-form-placeholder-formfield">' . $item . '</div>' . '</div>'; } // Wrap the label with help text $PA['label'] = $label = BackendUtility::wrapInHelp($table, $field, $label); // Create output value: if ($PA['fieldConf']['config']['form_type'] == 'user' && $PA['fieldConf']['config']['noTableWrapping']) { $out = $item; } elseif ($PA['palette']) { // Array: $out = array('NAME' => $label, 'ID' => $row['uid'], 'FIELD' => $field, 'TABLE' => $table, 'ITEM' => $item, 'ITEM_DISABLED' => $this->isDisabledNullValueField($table, $field, $row, $PA) ? ' disabled' : '', 'ITEM_NULLVALUE' => $this->renderNullValueWidget($table, $field, $row, $PA)); $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA); } else { // String: $out = array('NAME' => $label, 'ITEM' => $item, 'TABLE' => $table, 'ID' => $row['uid'], 'PAL_LINK_ICON' => $thePalIcon, 'FIELD' => $field, 'ITEM_DISABLED' => $this->isDisabledNullValueField($table, $field, $row, $PA) ? ' disabled' : '', 'ITEM_NULLVALUE' => $this->renderNullValueWidget($table, $field, $row, $PA)); $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA); // String: $out = $this->intoTemplate($out); } } } else { $this->commentMessages[] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']: Disabled by TSconfig'; } } // Hook: getSingleField_postProcess foreach ($this->hookObjectsSingleField as $hookObj) { if (method_exists($hookObj, 'getSingleField_postProcess')) { $hookObj->getSingleField_postProcess($table, $field, $row, $out, $PA, $this); } } // Return value (string or array) return $out; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $data Current data * @param array $config content of $PA['fieldConf']['config'] * @param bool $isVirtualRecord * @return string The HTML code of the header */ protected function renderForeignRecordHeader($parentUid, $foreign_table, $data, $config, $isVirtualRecord = false) { $rec = $data['databaseRow']; // Init: $domObjectId = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']); $objectId = $domObjectId . '-' . $foreign_table . '-' . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = (bool) (!$isOnSymmetricSide && $config['foreign_label']); $hasSymmetricLabel = (bool) $isOnSymmetricSide && $config['symmetric_label']; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = null; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $recTitle = $data['recordTitle']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; // Render title for everything else than group/db: if (isset($this->data['processedTca']['columns'][$titleCol]['config']['type']) && $this->data['processedTca']['columns'][$titleCol]['config']['type'] === 'group' && isset($this->data['processedTca']['columns'][$titleCol]['config']['internal_type']) && $this->data['processedTca']['columns'][$titleCol]['config']['internal_type'] === 'db') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, false); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(true); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, FormEngineUtility::databaseRowCompatibility($rec), true); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = '<span title="' . $altText . '" id="' . htmlspecialchars($objectId) . '_icon' . '">' . $this->iconFactory->getIconForRecord($foreign_table, $rec, Icon::SIZE_SMALL)->render() . '</span>'; $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $data, $config, $isVirtualRecord); $thumbnail = false; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode('|', array_shift(GeneralUtility::trimExplode(',', $fieldValue)))); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); if (!empty($rec['crop'])) { $imageSetup['crop'] = $rec['crop']; } $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing process was successful by checking if image width is set if ($processedImage->getProperty('width')) { $imageUrl = $processedImage->getPublicUrl(true); $thumbnail = '<img src="' . $imageUrl . '" ' . 'width="' . $processedImage->getProperty('width') . '" ' . 'height="' . $processedImage->getProperty('height') . '" ' . 'alt="' . htmlspecialchars($altText) . '" ' . 'title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = $mediaContainer . ' <div class="form-irre-header-cell form-irre-header-body">' . $label . '</div> <div class="form-irre-header-cell form-irre-header-control t3js-formengine-irre-control">' . $ctrl . '</div>'; return $header; }
/** * Returns the title (based on $code) of a record (from table $table) with the proper link around (that is for "pages"-records a link to the level of that record...) * * @param string $table Table name * @param integer $uid UID (not used here) * @param string $code Title string * @param array $row Records array (from table name) * @return string * @todo Define visibility */ public function linkWrapItems($table, $uid, $code, $row) { if (!$code) { $code = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title', 1) . ']</i>'; } else { $code = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitlePrep($code, $this->fixedL); } $title = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $row, FALSE, TRUE); $ficon = \TYPO3\CMS\Backend\Utility\IconUtility::getIcon($table, $row); $aOnClick = 'return insertElement(\'' . $table . '\', \'' . $row['uid'] . '\', \'db\', ' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($title) . ', \'\', \'\', \'' . $ficon . '\');'; $ATag = '<a href="#" onclick="' . $aOnClick . '">'; $ATag_alt = substr($ATag, 0, -4) . ',\'\',1);">'; $ATag_e = '</a>'; return $ATag . '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/plusbullet2.gif', 'width="18" height="16"') . ' title="' . $GLOBALS['LANG']->getLL('addToList', 1) . '" alt="" />' . $ATag_e . $ATag_alt . $code . $ATag_e; }
/** * Produces a table with indexing information for each page. * * @return string HTML output * @todo Define visibility */ public function drawTableOfIndexedPages() { global $BACK_PATH; // Drawing tree: $tree = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Tree\\View\\PageTreeView'); $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1); $tree->init('AND ' . $perms_clause); $HTML = '<img src="' . $BACK_PATH . \TYPO3\CMS\Backend\Utility\IconUtility::getIcon('pages', $this->pObj->pageinfo) . '" width="18" height="16" align="top" alt="" />'; $tree->tree[] = array('row' => $this->pObj->pageinfo, 'HTML' => $HTML); if ($this->pObj->MOD_SETTINGS['depth']) { $tree->getTree($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'], ''); } // Traverse page tree: $code = ''; foreach ($tree->tree as $data) { $code .= $this->indexed_info($data['row'], $data['HTML'] . $this->showPageDetails(BackendUtility::getRecordTitlePrep($data['row']['title']), $data['row']['uid'])); } if ($code) { $code = '<br /><br /> <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $this->printPhashRowHeader() . $code . '</table>'; // Create section to output: $theOutput .= $this->pObj->doc->section('', $code, 0, 1); } else { $theOutput .= $this->pObj->doc->section('', '<br /><br />' . $this->pObj->doc->icons(1) . 'There were no indexed pages found in the tree.<br /><br />', 0, 1); } return $theOutput; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = \TYPO3\CMS\Core\Database\RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // render using a self-defined user function if ($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc']) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = \TYPO3\CMS\Core\Utility\GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = \t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitlePrep($recTitle); if (!strcmp(trim($recTitle), '')) { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(\TYPO3\CMS\Backend\Utility\BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => 64, 'height' => 64), $imageSetup); $imageUrl = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, $imageSetup)->getPublicUrl(TRUE); $thumbnail = '<img src="' . $imageUrl . '" alt="' . htmlspecialchars($recTitle) . '">'; } else { $thumbnail = FALSE; } } } $altText = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $header = '<table>' . '<tr>' . (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail ? '<td class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</td>' : '<td class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</td>') . '<td class="t3-form-field-header-inline-summary">' . $label . '</td>' . '<td clasS="t3-form-field-header-inline-ctrl">' . $ctrl . '</td>' . '</tr>' . '</table>'; return $header; }
/** * Returns the title (based on $code) of a record (from table $table) with the proper link around (that is for "pages"-records a link to the level of that record...) * * @param string $table Table name * @param int $uid UID (not used here) * @param string $code Title string * @param array $row Records array (from table name) * @return string */ public function linkWrapItems($table, $uid, $code, $row) { if (!$code) { $code = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title', TRUE) . ']</i>'; } else { $code = BackendUtility::getRecordTitlePrep($code, $this->fixedL); } $title = BackendUtility::getRecordTitle($table, $row, FALSE, TRUE); $ficon = IconUtility::getSpriteIconForRecord($table, $row); $aOnClick = 'return insertElement(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($row['uid']) . ', \'db\', ' . GeneralUtility::quoteJSvalue($title) . ', \'\', \'\', ' . GeneralUtility::quoteJSvalue($ficon) . ');'; $ATag = '<a href="#" onclick="' . $aOnClick . '">'; $ATag_alt = substr($ATag, 0, -4) . ',\'\',1);">'; $ATag_e = '</a>'; return $ATag . IconUtility::getSpriteIcon('actions-edit-add', array('title' => $GLOBALS['LANG']->getLL('addToList', TRUE))) . $ATag_e . $ATag_alt . $code . $ATag_e; }