/** * 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; }
/** * 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 = 0, $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; // Make sure to load full $GLOBALS['TCA'] array for the table: \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($table); // 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']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']); // Now, check if this field is configured and editable (according to excludefields + other configuration) if (is_array($PA['fieldConf']) && !$skipThisField && (!$PA['fieldConf']['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field)) && $PA['fieldConf']['config']['form_type'] != 'passthrough' && ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE']) && (!$PA['fieldConf']['displayCond'] || $this->isDisplayCondition($PA['fieldConf']['displayCond'], $row)) && (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || strcmp($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 . ']'; // 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'] && \TYPO3\CMS\Core\Utility\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 ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($field, $typeField) || $GLOBALS['TCA'][$table]['ctrl']['requestUpdate'] && \TYPO3\CMS\Core\Utility\GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $field)) { if ($GLOBALS['BE_USER']->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. 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(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1); } else { $thePalIcon = ''; $palJSfunc = ''; } } // onFocus attribute to add to the field: $PA['onFocus'] = $palJSfunc && !$GLOBALS['BE_USER']->uc['dontShowPalettesOnFocusInAB'] ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"' : ''; // Find item $item = ''; $PA['label'] = $PA['altName'] ? $PA['altName'] : $PA['fieldConf']['label']; $PA['label'] = $PA['fieldTSConfig']['label'] ? $PA['fieldTSConfig']['label'] : $PA['label']; $PA['label'] = $PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] ? $PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->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(\TYPO3\CMS\Backend\Form\Element\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'] && (\TYPO3\CMS\Core\Utility\GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || \TYPO3\CMS\Core\Utility\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 = \TYPO3\CMS\Core\Utility\GeneralUtility::deHSCentities(htmlspecialchars($PA['label'])); if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !\TYPO3\CMS\Core\Utility\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>'; } // Wrap the label with help text $PA['label'] = $label = \TYPO3\CMS\Backend\Utility\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); $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); $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; }