[FEATURE] Allow TCA description property 97/57397/6
authorChristian Kuhn <lolli@schwarzbu.ch>
Wed, 27 Jun 2018 14:46:00 +0000 (16:46 +0200)
committerAndreas Wolf <andreas.wolf@typo3.org>
Wed, 18 Jul 2018 19:37:36 +0000 (21:37 +0200)
When the site configuration module has been introduced, it came
with a custom functionality to show an additional help text
when editing site records between the field label and the field input.

This useful feature is now changed into a general TCA feature
available everywhere: A new field information node expansion / "wizard"
is added to all form elements, the inline and flex containers: If
the property "description" is set for a TCA column type (same array
level as "label", it will show the value as localized string between
the field label and the input section.

There are three available render types for "wizard a-like" output:
* Field information - text between label+field
* Field control - buttons next to input sections like the link popup button
* Field wizards - clickable stuff below the input section, for example
  the localization state selector
If a field has been set to readOnly=true in TCA, field control and field
wizards do not make sense to render since they are meant to act with the
field value.
The field information node however has only informational character
which is useful for readOnly fields, too. Thus, this node expansion
type is now the only one that is always rendered, even if a field has
been set to readOnly.

Note this patch is fully covered by ext:styleguide (master) to have
examples for all changed elements now using the description property.

Resolves: #85410
Releases: master
Change-Id: Idcfacafa19b8208614b653b8fac22ce47bca3b8f
Reviewed-on: https://review.typo3.org/57397
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Jörg Bösche <typo3@joergboesche.de>
Tested-by: Jörg Bösche <typo3@joergboesche.de>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
34 files changed:
typo3/sysext/backend/Classes/Form/Container/FlexFormContainerContainer.php
typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php
typo3/sysext/backend/Classes/Form/Container/FlexFormNoTabsContainer.php
typo3/sysext/backend/Classes/Form/Container/FlexFormTabsContainer.php
typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php
typo3/sysext/backend/Classes/Form/Element/CheckboxElement.php
typo3/sysext/backend/Classes/Form/Element/CheckboxLabeledToggleElement.php
typo3/sysext/backend/Classes/Form/Element/CheckboxToggleElement.php
typo3/sysext/backend/Classes/Form/Element/GroupElement.php
typo3/sysext/backend/Classes/Form/Element/ImageManipulationElement.php
typo3/sysext/backend/Classes/Form/Element/InputColorPickerElement.php
typo3/sysext/backend/Classes/Form/Element/InputDateTimeElement.php
typo3/sysext/backend/Classes/Form/Element/InputLinkElement.php
typo3/sysext/backend/Classes/Form/Element/InputTextElement.php
typo3/sysext/backend/Classes/Form/Element/NoneElement.php
typo3/sysext/backend/Classes/Form/Element/RadioElement.php
typo3/sysext/backend/Classes/Form/Element/SelectCheckBoxElement.php
typo3/sysext/backend/Classes/Form/Element/SelectMultipleSideBySideElement.php
typo3/sysext/backend/Classes/Form/Element/SelectSingleBoxElement.php
typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php
typo3/sysext/backend/Classes/Form/Element/SelectTreeElement.php
typo3/sysext/backend/Classes/Form/Element/TextElement.php
typo3/sysext/backend/Classes/Form/Element/TextTableElement.php
typo3/sysext/backend/Classes/Form/FieldInformation/SiteConfiguration.php [deleted file]
typo3/sysext/backend/Classes/Form/FieldInformation/TcaDescription.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Form/NodeFactory.php
typo3/sysext/backend/Configuration/SiteConfiguration/site.php
typo3/sysext/backend/Configuration/SiteConfiguration/site_errorhandling.php
typo3/sysext/backend/Configuration/SiteConfiguration/site_language.php
typo3/sysext/backend/ext_localconf.php
typo3/sysext/core/Documentation/Changelog/master/Feature-85410-AllowTCADescriptionProperty.rst [new file with mode: 0644]
typo3/sysext/rsaauth/Classes/Form/Element/RsaInputElement.php
typo3/sysext/rte_ckeditor/Classes/Form/Element/RichTextElement.php
typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php

index 226a035..54ab93a 100644 (file)
@@ -82,6 +82,8 @@ class FlexFormContainerContainer extends AbstractContainer
             $containerTitle = $languageService->sL(trim($flexFormDataStructureArray['title']));
         }
 
+        $resultArray = $this->initializeResultArray();
+
         $html = [];
         $html[] = '<div class="t3-form-field-container-flexsections t3-flex-section t3js-flex-section">';
         $html[] =    '<input class="t3-flex-control t3js-flex-control-action" type="hidden" name="' . htmlspecialchars($actionFieldName) . '" value="" />';
@@ -113,7 +115,6 @@ class FlexFormContainerContainer extends AbstractContainer
         $html[] =    '</div>';
         $html[] = '</div>';
 
-        $resultArray = $this->initializeResultArray();
         $resultArray['html'] = implode(LF, $html);
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $containerContentResult, false);
 
index 87f7b1f..8592857 100644 (file)
@@ -82,6 +82,10 @@ class FlexFormElementContainer extends AbstractContainer
                     'label' => $parameterArray['label'],
                 ];
 
+                if (isset($flexFormFieldArray['description']) && !empty($flexFormFieldArray['description'])) {
+                    $fakeParameterArray['fieldConf']['description'] = $flexFormFieldArray['description'];
+                }
+
                 $alertMsgOnChange = '';
                 if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') {
                     if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
@@ -138,6 +142,7 @@ class FlexFormElementContainer extends AbstractContainer
 
                 // Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
                 $processedTitle = str_replace('\\n', '<br />', htmlspecialchars($fakeParameterArray['fieldConf']['label']));
+
                 $html = [];
                 $html[] = '<div class="form-section">';
                 $html[] =    '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">';
index d4170f8..b40ae71 100644 (file)
@@ -26,6 +26,17 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class FlexFormNoTabsContainer extends AbstractContainer
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Entry method
      *
      * @return array As defined in initializeResultArray() of AbstractNode
@@ -71,7 +82,14 @@ class FlexFormNoTabsContainer extends AbstractContainer
         $options['flexFormFormPrefix'] = '[data][' . $sheetName . '][lDEF]';
         $options['parameterArray'] = $parameterArray;
 
+        $resultArray = $this->initializeResultArray();
+
+        $fieldInformationResult = $this->renderFieldInformation();
+        $resultArray['html'] = '<div>' . $fieldInformationResult['html'] . '</div>';
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         $options['renderType'] = 'flexFormElementContainer';
-        return $this->nodeFactory->create($options)->render();
+        $childResult = $this->nodeFactory->create($options)->render();
+        return $this->mergeChildReturnIntoExistingResult($resultArray, $childResult, true);
     }
 }
index 70572dc..df27b14 100644 (file)
@@ -26,6 +26,17 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class FlexFormTabsContainer extends AbstractContainer
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Entry method
      *
      * @return array As defined in initializeResultArray() of AbstractNode
@@ -42,6 +53,7 @@ class FlexFormTabsContainer extends AbstractContainer
         $flexFormRowData = $this->data['flexFormRowData'];
 
         $resultArray = $this->initializeResultArray();
+
         $resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/Tabs';
 
         $domIdPrefix = 'DTM-' . GeneralUtility::shortMD5($this->data['parameterArray']['itemFormElName']);
@@ -94,7 +106,11 @@ class FlexFormTabsContainer extends AbstractContainer
             $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childReturn, false);
         }
 
-        $resultArray['html'] = $this->renderTabMenu($tabElements, $domIdPrefix);
+        $fieldInformationResult = $this->renderFieldInformation();
+        $resultArray['html'] = '<div>' . $fieldInformationResult['html'] . '</div>';
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
+        $resultArray['html'] .= $this->renderTabMenu($tabElements, $domIdPrefix);
         return $resultArray;
     }
 
index 8a56839..e2ecc5f 100644 (file)
@@ -63,6 +63,17 @@ class InlineControlContainer extends AbstractContainer
     protected $requireJsModules = [];
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * @var array Default wizards
      */
     protected $defaultFieldWizard = [
@@ -270,6 +281,11 @@ class InlineControlContainer extends AbstractContainer
         }
         // Wrap all inline fields of a record with a <div> (like a container)
         $html = '<div class="form-group" id="' . $nameObject . '">';
+
+        $fieldInformationResult = $this->renderFieldInformation();
+        $html .= $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         // Add the level links before all child records:
         if ($config['appearance']['levelLinksPosition'] === 'both' || $config['appearance']['levelLinksPosition'] === 'top') {
             $html .= '<div class="form-group t3js-formengine-validation-marker">' . $levelLinks . $localizationLinks . '</div>';
index cffae65..0f4cda8 100644 (file)
@@ -31,6 +31,17 @@ class CheckboxElement extends AbstractFormElement
     private $iconRegistry;
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -130,9 +141,7 @@ class CheckboxElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if (!$disabled) {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-wizards-wrap">';
         $html[] =       '<div class="form-wizards-element">';
         $html[] =           $elementHtml;
index a90214a..adfba81 100644 (file)
@@ -30,6 +30,17 @@ class CheckboxLabeledToggleElement extends AbstractFormElement
     private $iconRegistry;
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -129,9 +140,7 @@ class CheckboxLabeledToggleElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if (!$disabled) {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-wizards-wrap">';
         $html[] =       '<div class="form-wizards-element">';
         $html[] =           $elementHtml;
index 1f079bf..f3a63dc 100644 (file)
@@ -30,6 +30,17 @@ class CheckboxToggleElement extends AbstractFormElement
     private $iconRegistry;
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -129,9 +140,7 @@ class CheckboxToggleElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if (!$disabled) {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-wizards-wrap">';
         $html[] =       '<div class="form-wizards-element">';
         $html[] =           $elementHtml;
index f8dd6c9..a425f6e 100644 (file)
@@ -28,6 +28,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class GroupElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field controls for this element.
      *
      * @var array
@@ -175,10 +186,15 @@ class GroupElement extends AbstractFormElement
             );
         }
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if (isset($config['readOnly']) && $config['readOnly']) {
             // Return early if element is read only
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<select';
@@ -287,10 +303,6 @@ class GroupElement extends AbstractFormElement
             $selectorAttributes['multiple'] = 'multiple';
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldControlResult = $this->renderFieldControl();
         $fieldControlHtml = $fieldControlResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
index 07380da..1581ece 100644 (file)
@@ -79,6 +79,17 @@ class ImageManipulationElement extends AbstractFormElement
     ];
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
index 85bf99b..1aaee25 100644 (file)
@@ -25,6 +25,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class InputColorPickerElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -69,9 +80,14 @@ class InputColorPickerElement extends AbstractFormElement
         $width = (int)$this->formMaxWidth($size);
         $nullControlNameEscaped = htmlspecialchars('control[active][' . $table . '][' . $row['uid'] . '][' . $fieldName . ']');
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -149,10 +165,6 @@ class InputColorPickerElement extends AbstractFormElement
             $valuePickerHtml[] = '</select>';
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldWizardResult = $this->renderFieldWizard();
         $fieldWizardHtml = $fieldWizardResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
index bf83651..d8ed303 100644 (file)
@@ -26,6 +26,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class InputDateTimeElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -91,11 +102,16 @@ class InputDateTimeElement extends AbstractFormElement
         $size = MathUtility::forceIntegerInRange($config['size'] ?? $defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
         $width = (int)$this->formMaxWidth($size);
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if (isset($config['readOnly']) && $config['readOnly']) {
             // Early return for read only fields
             $itemValue = $this->formatValue($format, $itemValue);
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -160,10 +176,6 @@ class InputDateTimeElement extends AbstractFormElement
             $itemValue = gmdate('c', (int)$itemValue);
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldWizardResult = $this->renderFieldWizard();
         $fieldWizardHtml = $fieldWizardResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
index 3ad41f1..d47f477 100644 (file)
@@ -37,6 +37,17 @@ use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
 class InputLinkElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field controls render the link icon
      *
      * @var array
@@ -93,10 +104,15 @@ class InputLinkElement extends AbstractFormElement
         $width = (int)$this->formMaxWidth($size);
         $nullControlNameEscaped = htmlspecialchars('control[active][' . $table . '][' . $row['uid'] . '][' . $fieldName . ']');
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             // Early return for read only fields
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -186,10 +202,6 @@ class InputLinkElement extends AbstractFormElement
             $valuePickerHtml[] = '</select>';
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldWizardResult = $this->renderFieldWizard();
         $fieldWizardHtml = $fieldWizardResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
index 80bcfbf..42baeda 100644 (file)
@@ -28,6 +28,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class InputTextElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -72,6 +83,10 @@ class InputTextElement extends AbstractFormElement
         $width = (int)$this->formMaxWidth($size);
         $nullControlNameEscaped = htmlspecialchars('control[active][' . $table . '][' . $row['uid'] . '][' . $fieldName . ']');
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             // Early return for read only fields
             if (in_array('password', $evalList, true)) {
@@ -79,6 +94,7 @@ class InputTextElement extends AbstractFormElement
             }
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -199,10 +215,6 @@ class InputTextElement extends AbstractFormElement
             $valueSliderHtml[] = '</div>';
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldControlResult = $this->renderFieldControl();
         $fieldControlHtml = $fieldControlResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
index d9fec9e..c77a3e8 100644 (file)
@@ -22,11 +22,22 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 class NoneElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * This will render a non-editable display of the content of the field.
      *
-     * @return string The HTML code for the TCEform field
+     * @return array The HTML code for the TCEform field
      */
-    public function render()
+    public function render(): array
     {
         $resultArray = $this->initializeResultArray();
 
index a56fefa..1da7c55 100644 (file)
@@ -20,6 +20,17 @@ namespace TYPO3\CMS\Backend\Form\Element;
 class RadioElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -56,49 +67,47 @@ class RadioElement extends AbstractFormElement
             $disabled = ' disabled';
         }
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
+        $fieldWizardResult = $this->renderFieldWizard();
+        $fieldWizardHtml = $fieldWizardResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
+
         $html = [];
+        $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+        $html[] = $fieldInformationHtml;
+        $html[] =   '<div class="form-wizards-wrap">';
+        $html[] =       '<div class="form-wizards-element">';
+
         foreach ($this->data['parameterArray']['fieldConf']['config']['items'] as $itemNumber => $itemLabelAndValue) {
             $label = $itemLabelAndValue[0];
             $value = $itemLabelAndValue[1];
             $radioId = htmlspecialchars($this->data['parameterArray']['itemFormElID'] . '_' . $itemNumber);
             $radioChecked = (string)$value === (string)$this->data['parameterArray']['itemFormElValue'] ? ' checked="checked"' : '';
 
-            $fieldInformationResult = $this->renderFieldInformation();
-            $fieldInformationHtml = $fieldInformationResult['html'];
-            $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
-            $fieldWizardResult = $this->renderFieldWizard();
-            $fieldWizardHtml = $fieldWizardResult['html'];
-            $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
-
-            $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-            if (!$disabled) {
-                $html[] = $fieldInformationHtml;
-            }
-            $html[] =   '<div class="form-wizards-wrap">';
-            $html[] =       '<div class="form-wizards-element">';
-            $html[] =           '<div class="radio' . $disabled . '">';
-            $html[] =               '<label for="' . $radioId . '">';
-            $html[] =                   '<input type="radio"';
-            $html[] =                       ' name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
-            $html[] =                       ' id="' . $radioId . '"';
-            $html[] =                       ' value="' . htmlspecialchars($value) . '"';
-            $html[] =                       $radioChecked;
-            $html[] =                       $disabled;
-            $html[] =                       ' onclick="' . htmlspecialchars(implode('', $this->data['parameterArray']['fieldChangeFunc'])) . '"';
-            $html[] =                   '/>';
-            $html[] =                       htmlspecialchars($this->appendValueToLabelInDebugMode($label, $value));
-            $html[] =               '</label>';
-            $html[] =           '</div>';
-            $html[] =       '</div>';
-            if (!$disabled) {
-                $html[] =   '<div class="form-wizards-items-bottom">';
-                $html[] =       $fieldWizardHtml;
-                $html[] =   '</div>';
-            }
-            $html[] =   '</div>';
+            $html[] = '<div class="radio' . $disabled . '">';
+            $html[] =     '<label for="' . $radioId . '">';
+            $html[] =     '<input type="radio"';
+            $html[] =         ' name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
+            $html[] =         ' id="' . $radioId . '"';
+            $html[] =         ' value="' . htmlspecialchars($value) . '"';
+            $html[] =         $radioChecked;
+            $html[] =         $disabled;
+            $html[] =         ' onclick="' . htmlspecialchars(implode('', $this->data['parameterArray']['fieldChangeFunc'])) . '"';
+            $html[] =     '/>';
+            $html[] =         htmlspecialchars($this->appendValueToLabelInDebugMode($label, $value));
+            $html[] =     '</label>';
             $html[] = '</div>';
         }
+        if (!$disabled) {
+            $html[] =   '<div class="form-wizards-items-bottom">';
+            $html[] =       $fieldWizardHtml;
+            $html[] =   '</div>';
+        }
+        $html[] =   '</div>';
+        $html[] = '</div>';
 
         $resultArray['html'] = implode(LF, $html);
         return $resultArray;
index 96586ce..63a39ff 100644 (file)
@@ -28,6 +28,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class SelectCheckBoxElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -145,9 +156,7 @@ class SelectCheckBoxElement extends AbstractFormElement
             $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
 
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-            if (!$disabled) {
-                $html[] = $fieldInformationHtml;
-            }
+            $html[] = $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
 
index 258ed51..ba9ee4a 100644 (file)
@@ -29,6 +29,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class SelectMultipleSideBySideElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field controls for this element.
      *
      * @var array
@@ -325,6 +336,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
     protected function renderReadOnly()
     {
         $languageService = $this->getLanguageService();
+        $resultArray = $this->initializeResultArray();
 
         $parameterArray = $this->data['parameterArray'];
         $config = $parameterArray['fieldConf']['config'];
@@ -363,8 +375,13 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
             }
         }
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+        $html[] =   $fieldInformationHtml;
         $html[] =   '<div class="form-wizards-wrap">';
         $html[] =       '<div class="form-wizards-element">';
         $html[] =           '<label>';
@@ -389,7 +406,6 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
         $html[] =   '</div>';
         $html[] = '</div>';
 
-        $resultArray = $this->initializeResultArray();
         $resultArray['html'] = implode(LF, $html);
         return $resultArray;
     }
index ff20f70..eacd0a6 100644 (file)
@@ -26,6 +26,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class SelectSingleBoxElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field controls for this element.
      *
      * @var array
@@ -112,9 +123,7 @@ class SelectSingleBoxElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if (!$disabled) {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
         $html[] =       '<div class="form-wizards-wrap form-wizards-aside">';
         $html[] =           '<div class="form-wizards-element">';
index a305ca3..265afe1 100644 (file)
@@ -28,6 +28,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class SelectSingleElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -200,9 +211,7 @@ class SelectSingleElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if (!$disabled) {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-control-wrap">';
         $html[] =       '<div class="form-wizards-wrap">';
         $html[] =           '<div class="form-wizards-element">';
index 4b1020c..079b0db 100644 (file)
@@ -22,6 +22,17 @@ namespace TYPO3\CMS\Backend\Form\Element;
 class SelectTreeElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * @var array Default wizards
      */
     protected $defaultFieldWizard = [
@@ -124,9 +135,7 @@ class SelectTreeElement extends AbstractFormElement
 
         $html = [];
         $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
-        if ($readOnly === 'false') {
-            $html[] = $fieldInformationHtml;
-        }
+        $html[] = $fieldInformationHtml;
         $html[] =   '<div class="form-control-wrap">';
         $html[] =       '<div class="form-wizards-wrap">';
         $html[] =           '<div class="form-wizards-element">';
index 786950d..ccf588a 100644 (file)
@@ -26,6 +26,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class TextElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -94,9 +105,14 @@ class TextElement extends AbstractFormElement
             }
         }
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -189,10 +205,6 @@ class TextElement extends AbstractFormElement
             $valuePickerHtml[] = '</select>';
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldControlResult = $this->renderFieldControl();
         $fieldControlHtml = $fieldControlResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
index f534ec1..e49a3e2 100644 (file)
@@ -25,6 +25,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class TextTableElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -99,9 +110,14 @@ class TextTableElement extends AbstractFormElement
             }
         }
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -168,10 +184,6 @@ class TextTableElement extends AbstractFormElement
             $attributes['placeholder'] = htmlspecialchars(trim($config['placeholder']));
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldControlResult = $this->renderFieldControl();
         $fieldControlHtml = $fieldControlResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
diff --git a/typo3/sysext/backend/Classes/Form/FieldInformation/SiteConfiguration.php b/typo3/sysext/backend/Classes/Form/FieldInformation/SiteConfiguration.php
deleted file mode 100644 (file)
index 95949a7..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Backend\Form\FieldInformation;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Form\AbstractNode;
-use TYPO3\CMS\Core\Localization\LanguageService;
-
-/**
- * Provides field information texts for form engine fields concerning site configuration module
- */
-class SiteConfiguration extends AbstractNode
-{
-    /**
-     * Handler for single nodes
-     *
-     * @return array As defined in initializeResultArray() of AbstractNode
-     */
-    public function render()
-    {
-        $resultArray = $this->initializeResultArray();
-        $fieldInformationText = $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:' . $this->data['tableName'] . '.' . $this->data['fieldName']);
-        if ($fieldInformationText !== $this->data['fieldName']) {
-            $resultArray['html'] = $fieldInformationText;
-        }
-        return $resultArray;
-    }
-
-    /**
-     * Returns the LanguageService
-     *
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-}
diff --git a/typo3/sysext/backend/Classes/Form/FieldInformation/TcaDescription.php b/typo3/sysext/backend/Classes/Form/FieldInformation/TcaDescription.php
new file mode 100644 (file)
index 0000000..3c57f44
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Backend\Form\FieldInformation;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Form\AbstractNode;
+use TYPO3\CMS\Core\Localization\LanguageService;
+
+/**
+ * Render localized ['columns']['theField']['description'] text as default
+ * field information node. This is typically displayed in elements below the
+ * element label and the field content.
+ */
+class TcaDescription extends AbstractNode
+{
+    /**
+     * Handler for single nodes
+     *
+     * @return array As defined in initializeResultArray() of AbstractNode
+     */
+    public function render(): array
+    {
+        $resultArray = $this->initializeResultArray();
+        if (!empty($this->data['parameterArray']['fieldConf']['description'])) {
+            $fieldInformationText = $this->getLanguageService()->sL($this->data['parameterArray']['fieldConf']['description']);
+            if (trim($fieldInformationText) !== '') {
+                $resultArray['html'] = htmlspecialchars($fieldInformationText);
+            }
+        }
+        return $resultArray;
+    }
+
+    /**
+     * Returns the LanguageService
+     *
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+}
index 46a1759..7b867fd 100644 (file)
@@ -98,6 +98,9 @@ class NodeFactory
         'fieldInformation' => NodeExpansion\FieldInformation::class,
         'fieldWizard' => NodeExpansion\FieldWizard::class,
 
+        // Element information
+        'tcaDescription' => FieldInformation\TcaDescription::class,
+
         // Element wizards
         'defaultLanguageDifferences' => FieldWizard\DefaultLanguageDifferences::class,
         'fileThumbnails' => FieldWizard\FileThumbnails::class,
index ab4ae85..58e3c6b 100644 (file)
@@ -11,6 +11,7 @@ return [
     'columns' => [
         'identifier' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site.identifier',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site.identifier',
             'config' => [
                 'type' => 'input',
                 'size' => 35,
@@ -18,11 +19,6 @@ return [
                 // identifier is used as directory name - allow a-z,0-9,_,- as chars only.
                 // unique is additionally checked server side
                 'eval' => 'required,lower,alphanum_x',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'rootPageId' => [
@@ -33,23 +29,14 @@ return [
                 'renderType' => 'selectSingle',
                 'foreign_table' => 'pages',
                 'foreign_table_where' => ' AND (is_siteroot=1 OR (pid=0 AND doktype IN (1,6,7))) AND l10n_parent = 0 ORDER BY pid, sorting',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'base' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site.base',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site.base',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'languages' => [
index 71e9ed5..1b6ebf0 100644 (file)
@@ -16,6 +16,7 @@ return [
     'columns' => [
         'errorCode' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorCode',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_errorhandling.errorCode',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required, trim, int',
@@ -35,11 +36,6 @@ return [
                         ['LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorCode.0', '0'],
                     ],
                 ],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorHandler' => [
@@ -53,56 +49,32 @@ return [
                     ['Show Content from Page', 'Page'],
                     ['PHP Class (must implement the PageErrorHandlerInterface)', 'PHP'],
                 ],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorFluidTemplate' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorFluidTemplate',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_errorhandling.errorFluidTemplate',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorFluidTemplatesRootPath' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorFluidTemplatesRootPath',
             'config' => [
                 'type' => 'input',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorFluidLayoutsRootPath' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorFluidLayoutsRootPath',
             'config' => [
                 'type' => 'input',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorFluidPartialsRootPath' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorFluidPartialsRootPath',
             'config' => [
                 'type' => 'input',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'errorContentSource' => [
@@ -111,11 +83,6 @@ return [
                 'type' => 'input',
                 'renderType' => 'inputLink',
                 'eval' => 'required',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
                 'fieldControl' => [
                     'linkPopup' => [
                         'options' => [
@@ -127,14 +94,10 @@ return [
         ],
         'errorPhpClassFQCN' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_errorhandling.errorPhpClassFQCN',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_errorhandling.errorPhpClassFQCN',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
     ],
index 28caf8f..f3ff5b4 100644 (file)
@@ -21,11 +21,6 @@ return [
                 'size' => 1,
                 'min' => 1,
                 'max' => 1,
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'title' => [
@@ -35,11 +30,6 @@ return [
                 'size' => 10,
                 'eval' => 'required',
                 'placeholder' => 'English',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'navigationTitle' => [
@@ -48,37 +38,24 @@ return [
                 'type' => 'input',
                 'size' => 10,
                 'placeholder' => 'English',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'base' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_language.base',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_language.base',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required',
                 'default' => '/',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'locale' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_language.locale',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_language.locale',
             'config' => [
                 'type' => 'input',
                 'eval' => 'required',
                 'placeholder' => 'en_US.UTF-8',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'iso-639-1' => [
@@ -88,11 +65,6 @@ return [
                 'renderType' => 'selectSingle',
                 // Fed by data provider
                 'items' => [],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'hreflang' => [
@@ -100,11 +72,6 @@ return [
             'config' => [
                 'type' => 'input',
                 'placeholder' => 'en-US',
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'direction' => [
@@ -117,25 +84,16 @@ return [
                     ['Left to Right', 'ltr', ''],
                     ['Right to Left', 'rtl', ''],
                 ],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'typo3Language' => [
             'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site_language.typo3Language',
+            'description' => 'LLL:EXT:backend/Resources/Private/Language/siteconfiguration_fieldinformation.xlf:site_language.typo3Language',
             'config' => [
                 'type' => 'select',
                 'renderType' => 'selectSingle',
                 // Fed by data provider
                 'items' => [],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
                 'default' => 'default'
             ],
         ],
@@ -404,11 +362,6 @@ return [
                         'disabled' => false,
                     ],
                 ],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'fallbackType' => [
@@ -422,11 +375,6 @@ return [
                     ['No fallback (strict)', 'strict'],
                     ['Fallback to other language', 'fallback'],
                 ],
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
         'fallbacks' => [
@@ -441,11 +389,6 @@ return [
                 'foreign_table' => 'sys_language',
                 'size' => 5,
                 'min' => 0,
-                'fieldInformation' => [
-                    'SiteConfigurationModuleFieldInformation' => [
-                        'renderType' => 'SiteConfigurationModuleFieldInformation',
-                    ],
-                ],
             ],
         ],
     ],
index c06b037..073da8d 100644 (file)
@@ -43,10 +43,3 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch']['page'] = 'pages';
 
 // Register BackendLayoutDataProvider for PageTs
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']['pagets'] = \TYPO3\CMS\Backend\Provider\PageTsBackendLayoutDataProvider::class;
-
-// Register fieldInformation Provider for site configuration module
-$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1522919823] = [
-    'nodeName' => 'SiteConfigurationModuleFieldInformation',
-    'priority' => '70',
-    'class' => \TYPO3\CMS\Backend\Form\FieldInformation\SiteConfiguration::class
-];
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-85410-AllowTCADescriptionProperty.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-85410-AllowTCADescriptionProperty.rst
new file mode 100644 (file)
index 0000000..21dca74
--- /dev/null
@@ -0,0 +1,40 @@
+.. include:: ../../Includes.txt
+
+================================================
+Feature: #85410 - Allow TCA description property
+================================================
+
+See :issue:`85410`
+
+Description
+===========
+
+The new `TCA` property `description` on column field level has been introduced.
+The value data type is a localized string, similar and on the same level as `label`.
+
+The property can be used to display an additional help text between the field label and
+the user input when editing records. As an example, the core uses the description property
+in the site configuration module when editing a site on some properties like `identifier`.
+
+The property is available on all common `TCA` types like `input` and `select` and so on.
+
+Example::
+
+    'columns' => [
+        'myField' => [
+            'label' => 'My label',
+            'description' => 'LLL:EXT:my_ext/Resources/Private/Language/locallang_tca.xlf:field.description',
+            'config' => [
+                'type' => 'input',
+            ],
+        ],
+    ],
+
+
+Impact
+======
+
+The change is fully backwards compatible and can be used by integrators or administrators
+to hint editors for expected field input.
+
+.. index:: Backend, FlexForm, TCA
index 6a5e858..18b380c 100644 (file)
@@ -25,6 +25,17 @@ use TYPO3\CMS\Core\Utility\StringUtility;
 class RsaInputElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
@@ -60,6 +71,10 @@ class RsaInputElement extends AbstractFormElement
         $width = (int)$this->formMaxWidth($size);
         $isPasswordField = in_array('password', $evalList, true);
 
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
         if ($config['readOnly']) {
             // Early return for read only fields
             if ($isPasswordField) {
@@ -67,6 +82,7 @@ class RsaInputElement extends AbstractFormElement
             }
             $html = [];
             $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
             $html[] =   '<div class="form-wizards-wrap">';
             $html[] =       '<div class="form-wizards-element">';
             $html[] =           '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
@@ -137,10 +153,6 @@ class RsaInputElement extends AbstractFormElement
             $attributes['autocomplete'] = 'new-' . $fieldName;
         }
 
-        $fieldInformationResult = $this->renderFieldInformation();
-        $fieldInformationHtml = $fieldInformationResult['html'];
-        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
         $fieldControlResult = $this->renderFieldControl();
         $fieldControlHtml = $fieldControlResult['html'];
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
index c60afd4..a12b8bd 100644 (file)
@@ -28,6 +28,17 @@ use TYPO3\CMS\Core\Utility\PathUtility;
 class RichTextElement extends AbstractFormElement
 {
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array
index 59aee66..600f299 100644 (file)
@@ -49,6 +49,17 @@ class T3editorElement extends AbstractFormElement
     protected $extPath = '';
 
     /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
      * Default field wizards enabled for this element.
      *
      * @var array