[FEATURE] Allow deactivation of FormDataProviders 24/55724/3
authorChristian Kuhn <lolli@schwarzbu.ch>
Thu, 15 Feb 2018 00:18:44 +0000 (01:18 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 17 Feb 2018 20:07:43 +0000 (21:07 +0100)
To manipulate the FormEngine data provider list by extensions,
it can be helpful to just set a data provider as disabled
and add an own one after the disabled one and before the
next one. This avoids funny array munging and dependency
shuffling if an extension author needs to substitute an
entire data provider with an own solution.

The concept has been implemented for node expansion
render types in a similar way and is repeated here.

Change-Id: Ia1f2de94940248b60e851c7b9968539f5ab0ef79
Resolves: #83906
Releases: master
Reviewed-on: https://review.typo3.org/55724
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/backend/Classes/Form/FormDataGroup/OrderedProviderList.php
typo3/sysext/backend/Tests/Unit/Form/FormDataGroup/OrderedProviderListTest.php
typo3/sysext/core/Documentation/Changelog/master/Feature-83906-DisableSingleFormEngineDataProvider.rst [new file with mode: 0644]

index 1a90d3f..2d677f0 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Backend\Form\FormDataGroup;
 
 /*
@@ -27,9 +28,8 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class OrderedProviderList implements FormDataGroupInterface
 {
-
     /**
-     * @var array<FormDataProviderInterface>
+     * @var FormDataProviderInterface[]
      */
     protected $providerList = [];
 
@@ -40,12 +40,17 @@ class OrderedProviderList implements FormDataGroupInterface
      * @return array Result filled with data
      * @throws \UnexpectedValueException
      */
-    public function compile(array $result)
+    public function compile(array $result): array
     {
         $orderingService = GeneralUtility::makeInstance(DependencyOrderingService::class);
         $orderedDataProvider = $orderingService->orderByDependencies($this->providerList, 'before', 'depends');
 
-        foreach ($orderedDataProvider as $providerClassName => $_) {
+        foreach ($orderedDataProvider as $providerClassName => $providerConfig) {
+            if (isset($providerConfig['disabled']) && $providerConfig['disabled'] === true) {
+                // Skip this data provider if disabled by configuration
+                continue;
+            }
+
             /** @var FormDataProviderInterface $provider */
             $provider = GeneralUtility::makeInstance($providerClassName);
 
index 123aa73..8eb022d 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataGroup;
 
 /*
@@ -20,23 +21,14 @@ use TYPO3\CMS\Backend\Form\FormDataGroup\OrderedProviderList;
 use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
 use TYPO3\CMS\Core\Service\DependencyOrderingService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
  * Test case
  */
-class OrderedProviderListTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class OrderedProviderListTest extends UnitTestCase
 {
     /**
-     * @var OrderedProviderList
-     */
-    protected $subject;
-
-    protected function setUp()
-    {
-        $this->subject = new OrderedProviderList();
-    }
-
-    /**
      * @test
      */
     public function compileReturnsIncomingData()
@@ -48,8 +40,9 @@ class OrderedProviderListTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
 
         $input = ['foo'];
 
-        $this->subject->setProviderList([]);
-        $this->assertEquals($input, $this->subject->compile($input));
+        $subject = new OrderedProviderList();
+        $subject->setProviderList([]);
+        $this->assertEquals($input, $subject->compile($input));
     }
 
     /**
@@ -68,10 +61,31 @@ class OrderedProviderListTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
         $providerResult = ['foo'];
         $formDataProviderProphecy->addData(Argument::cetera())->shouldBeCalled()->willReturn($providerResult);
 
-        $this->subject->setProviderList([
+        $subject = new OrderedProviderList();
+        $subject->setProviderList([
             FormDataProviderInterface::class => [],
         ]);
-        $this->assertEquals($providerResult, $this->subject->compile([]));
+        $this->assertEquals($providerResult, $subject->compile([]));
+    }
+
+    /**
+     * @test
+     */
+    public function compileDoesNotCallDisabledDataProvider()
+    {
+        /** @var DependencyOrderingService|ObjectProphecy $orderingServiceProphecy */
+        $orderingServiceProphecy = $this->prophesize(DependencyOrderingService::class);
+        GeneralUtility::addInstance(DependencyOrderingService::class, $orderingServiceProphecy->reveal());
+        $orderingServiceProphecy->orderByDependencies(Argument::cetera())->willReturnArgument(0);
+
+        $subject = new OrderedProviderList();
+        $subject->setProviderList([
+            FormDataProviderInterface::class => [
+                'disabled' => true,
+            ],
+        ]);
+        $input = ['foo'];
+        $this->assertEquals($input, $subject->compile($input));
     }
 
     /**
@@ -91,9 +105,10 @@ class OrderedProviderListTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
         $this->expectException(\UnexpectedValueException::class);
         $this->expectExceptionCode(1485299408);
 
-        $this->subject->setProviderList([
+        $subject = new OrderedProviderList();
+        $subject->setProviderList([
             \stdClass::class => [],
         ]);
-        $this->subject->compile([]);
+        $subject->compile([]);
     }
 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-83906-DisableSingleFormEngineDataProvider.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-83906-DisableSingleFormEngineDataProvider.rst
new file mode 100644 (file)
index 0000000..17a6238
--- /dev/null
@@ -0,0 +1,36 @@
+.. include:: ../../Includes.txt
+
+=========================================================
+Feature: #83906 - Disable single FormEngine data provider
+=========================================================
+
+See :issue:`83906`
+
+Description
+===========
+
+Single data providers used in the FormEngine data compilation step can be
+disabled.
+
+As an example, if editing a full database record, the default TcaCheckboxItems
+could be shut down by setting :php:`disabled` in the :php:`tcaDatabaseRecord` group in
+an extensions :file:`ext_localconf.php` file:
+
+.. code-block:: php
+
+    $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
+    [\TYPO3\CMS\Backend\Form\FormDataProvider\TcaCheckboxItems::class]['disabled'] = true;
+
+Extension authors can then add an own data provider which :php:`depends` on the disabled one
+and is :php:`before` of the next one to effectively substitute single providers with own
+solutions if needed.
+
+
+Impact
+======
+
+The disable feature allows extension authors to easily substitute
+existing data providers with own solutions and avoids nasty array
+and dependency munging by extension authors.
+
+.. index:: Backend, PHP-API
\ No newline at end of file