[TASK] Deprecate TCA type=user without renderType 98/58198/3
authorChristian Kuhn <lolli@schwarzbu.ch>
Thu, 6 Sep 2018 10:17:49 +0000 (12:17 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 7 Sep 2018 18:56:09 +0000 (20:56 +0200)
Using a custom renderType instead of a userFunc for
type=user TCA elements is much more flexible and suits
better into the overall FormEngine node construct.

The patch deprecates userFunc and outlines details on
how existing ones can be migrated over to custom renderTypes
without much hassle.

Resolves: #86163
Related: #86109
Releases: master
Change-Id: I2bad5f79dab5643efe7f8dc959e788b9426bfdd6
Reviewed-on: https://review.typo3.org/58198
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/backend/Classes/Form/Element/UserElement.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-86163-TCATypeuserWithoutRenderType.rst [new file with mode: 0644]

index 09a73f7..dfb9368 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Backend\Form\Element;
 
 /*
@@ -17,7 +18,11 @@ namespace TYPO3\CMS\Backend\Form\Element;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
- * Generation of elements of the type "user"
+ * Generation of elements of the type "user". This is a dummy implementation.
+ *
+ * type="user" elements should be combined with a custom renderType to create custom output.
+ * This implementation registered for type="user" kicks in if no renderType is given and is just
+ * a fallback implementation to hint developers that the TCA registration is incomplete.
  */
 class UserElement extends AbstractFormElement
 {
@@ -28,9 +33,27 @@ class UserElement extends AbstractFormElement
      */
     public function render()
     {
+        $parameterArray = $this->data['parameterArray'];
         $resultArray = $this->initializeResultArray();
 
-        $parameterArray = $this->data['parameterArray'];
+        if (empty($parameterArray['fieldConf']['config']['userFunc'])) {
+            // If there is no (deprecated) userFunc, render some dummy output to explain this element
+            // should usually not be called at all.
+            // @deprecated The if can be removed in v10, keeping the body only.
+            $resultArray['html'] = '<div class="alert alert-warning">';
+            $resultArray['html'] .= 'This is dummy output: Field <code>' . htmlspecialchars($this->data['fieldName']) . '</code>';
+            $resultArray['html'] .= 'of table <code>' . htmlspecialchars($this->data['tableName']) . '</code>';
+            $resultArray['html'] .= ' is registered as type="user" element without a specific renderType.';
+            $resultArray['html'] .= ' Please look up details in TCA reference documentation for type="user".';
+            $resultArray['html'] .= '</div>';
+            return $resultArray;
+        }
+
+        // @deprecated since TYPO3 v9, everything below will be removed in v10.
+        trigger_error(
+            'Properties "userFunc", "noTableWrapping" and "parameters" have been deprecated in v9, will be removed in v10. Use a renderType instead.',
+            E_USER_DEPRECATED
+        );
         $parameterArray['table'] = $this->data['tableName'];
         $parameterArray['field'] = $this->data['fieldName'];
         $parameterArray['row'] = $this->data['databaseRow'];
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86163-TCATypeuserWithoutRenderType.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86163-TCATypeuserWithoutRenderType.rst
new file mode 100644 (file)
index 0000000..191d2b1
--- /dev/null
@@ -0,0 +1,111 @@
+.. include:: ../../Includes.txt
+
+========================================================
+Deprecation: #86163 - TCA type="user" without renderType
+========================================================
+
+See :issue:`86163`
+
+Description
+===========
+
+The following `TCA` properties on :php:`type="user"` config types have been deprecated and
+should not be used any longer:
+
+* :php:`userFunc`
+* :php:`parameters`
+* :php:`noTableWrapping`
+
+
+Impact
+======
+
+This especially means that :php:`userFunc` should not be used any longer on `TCA` fields
+registered as config type :php:`user`. Those can be substituted with a custom :php:`renderType`
+since TYPO3 v7. See example below for more details on this.
+
+
+Affected Installations
+======================
+
+Instances are affected if an extension registers a :php:`type=user` `TCA` config type with a
+custom :php:`userFunc`. If a field uses the :php:`userFunc` property, a PHP :php:`E_USER_DEPRECATED`
+error is triggered during rendering.
+
+
+Migration
+=========
+
+:php:`userFunc` implementations can switched to use a custom :php:`renderType` as outlined
+in the :ref:`FormEngine documentation <t3coreapi:FormEngine-Rendering-NodeFactory>`. The TYPO3 core
+did that for example with the `is_public` field of table `sys_file_storge` in patch 58141_.
+
+To switch from a :php:`userFunc` implementation to a :php:`renderType`, an extension typically has
+to register an own element node in :file:`ext_localconf.php`. Then change the user function to a class
+that extends :php:`AbstractFormElement` where method :php:`render()` returns an array as defined
+my helper method :php:`initializeResultArray`. The `HTML` created by the former user function should be
+returned in :php:`$resultArray['html']`, parameters like the `tableName` can be found in :php:`$this->data`.
+
+Note the `renderType` variant can additionally load custom `JavaScript` and `CSS` using further parts of the
+result array, typically :php:`requireJsModules` and :php:`stylesheetFiles`. Additional arguments to the element
+can be defined by using any property within the `config` section, it is up to the specific `renderType` to
+do this, using `parameters` as property key is probably a good idea, though.
+
+As example, imagine a `TCA` user element has been defined like this in the `columns` section::
+
+    'myMapElement' = [
+        'label' => 'My map element'
+        'config' => [
+            'type' => 'user',
+            'userFunc' => 'Vendor\Extension\Tca\UserFunc\MyMap->render',
+            'parameters' => [
+                'useOpenStreetMap' => true,
+            ],
+        ],
+    ],
+
+This should be adapted to a registered node element class::
+
+    // Register a node in ext_localconf.php
+    $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][<unix timestamp of "now">] = [
+        'nodeName' => 'lollisCustomMapElement',
+        'priority' => 40,
+        'class' => \Vendor\Extension\Form\Element\LollisCustomMapElement::class,
+    ];
+
+With a `TCA` registration like this to delegate the element rendering to the registered class::
+
+    'myMapElement' = [
+        'label' => 'My map element'
+        'config' => [
+            'type' => 'user',
+            'renderType' => 'lollisCustomMapElement',
+            'parameters' => [
+                'useOpenStreetMap' => true,
+            ],
+        ],
+    ],
+
+And a class implementation that extends :php:`AbstractFormElement`::
+
+    <?php
+    declare(strict_types = 1);
+    namespace Vendor\Extension\Form\Element;
+
+    use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
+
+    class LollisCustomMapElement extends AbstractFormElement
+    {
+        public function render()
+        {
+            // Custom TCA properties and other data can be found in $this->data, for example the above
+            // parameters are available in $this->data['parameterArray']['fieldConf']['config']['parameters']
+            $result = $this->initializeResultArray();
+            $result['html'] = 'my map content';
+            return $result;
+        }
+    }
+
+.. _58141: https://review.typo3.org/#/c/58141/
+
+.. index:: Backend, TCA, NotScanned
\ No newline at end of file