From 14a8aa115cfbabe9735ced4a5c8f8533bc08bfd8 Mon Sep 17 00:00:00 2001
From: Alexander Nitsche <typo3@alexandernitsche.com>
Date: Fri, 20 Aug 2021 21:56:12 +0200
Subject: [PATCH] [BUGFIX] Re-enable reset of excluded records in EXT:impexp

This is a regression introduced with #94057 that causes resetting
excluded records to throw an exception in the export view, since the
incoming parameter "exclude" could be of type array (= add excluded
records) or integer (= include all records again), but was only
checked for null or not null, which was ambiguous in the second case.
For clear separation the reset of excluded records is now done via a
new parameter "resetExclude".

Resolves: #94949
Releases: master
Change-Id: Iddb8d21e0f75cc24ef18dd2f851a479cb7dafb3b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70690
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Alexander Nitsche <typo3@alexandernitsche.com>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Alexander Nitsche <typo3@alexandernitsche.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../Classes/Controller/ExportController.php   |  5 ++-
 .../Partials/Export/Configuration.html        |  4 +-
 .../Export/ExportControllerTest.php           | 39 +++++++++++++++++++
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/typo3/sysext/impexp/Classes/Controller/ExportController.php b/typo3/sysext/impexp/Classes/Controller/ExportController.php
index 73bf7a8e6312..15b53a1d502a 100644
--- a/typo3/sysext/impexp/Classes/Controller/ExportController.php
+++ b/typo3/sysext/impexp/Classes/Controller/ExportController.php
@@ -129,8 +129,9 @@ class ExportController extends ImportExportController
         if (!array_key_exists('excludeDisabled', $inData)) {
             $inData['excludeDisabled'] = 1;
         }
-        // Set exclude fields in export object:
-        $inData['exclude'] ??= [];
+        if ($inData['resetExclude'] ?? false) {
+            $inData['exclude'] = [];
+        }
         $inData['preset']['public'] = (int)($inData['preset']['public'] ?? 0);
         return $inData;
     }
diff --git a/typo3/sysext/impexp/Resources/Private/Partials/Export/Configuration.html b/typo3/sysext/impexp/Resources/Private/Partials/Export/Configuration.html
index 16996de357c6..fc74e313c232 100644
--- a/typo3/sysext/impexp/Resources/Private/Partials/Export/Configuration.html
+++ b/typo3/sysext/impexp/Resources/Private/Partials/Export/Configuration.html
@@ -150,9 +150,9 @@
                     </f:if>
                 </f:for>
                 <div class="form-check">
-                    <input type="checkbox" name="tx_impexp[exclude]" id="checkExclude" value="1"
+                    <input type="checkbox" name="tx_impexp[resetExclude]" id="checkResetExclude" value="1"
                         class="form-check-input" />
-                    <label for="checkExclude" class="form-check-label">
+                    <label for="checkResetExclude" class="form-check-label">
                         <f:translate key="makeconfig_clearAllManualExclusions" />
                     </label>
                 </div>
diff --git a/typo3/sysext/impexp/Tests/Functional/Export/ExportControllerTest.php b/typo3/sysext/impexp/Tests/Functional/Export/ExportControllerTest.php
index 85409e283366..c0fac55fd79a 100644
--- a/typo3/sysext/impexp/Tests/Functional/Export/ExportControllerTest.php
+++ b/typo3/sysext/impexp/Tests/Functional/Export/ExportControllerTest.php
@@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Impexp\Controller\ExportController;
+use TYPO3\CMS\Impexp\Export;
 use TYPO3\CMS\Impexp\Tests\Functional\AbstractImportExportTestCase;
 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
 
@@ -63,6 +64,44 @@ class ExportControllerTest extends AbstractImportExportTestCase
         self::assertArrayHasKey('tx_impexp_presets', $tables);
     }
 
+    public function resetExcludedRecordsDataProvider(): array
+    {
+        return [
+            [
+                ['exclude' => ['tt_content:1' => '1', 'tt_content:2' => '1']],
+                ['tt_content:1' => '1', 'tt_content:2' => '1']
+            ],
+            [
+                ['exclude' => ['tt_content:1' => '1', 'tt_content:2' => '1'], 'resetExclude' => 1],
+                []
+            ]
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider resetExcludedRecordsDataProvider
+     */
+    public function resetExcludedRecords(array $requestParams, array $expected): void
+    {
+        $request = (new ServerRequest())
+            ->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE)
+            ->withParsedBody([
+                'tx_impexp' => array_merge(['download_export' => 1], $requestParams)
+            ]);
+
+        try {
+            $this->exportControllerMock->mainAction($request);
+        } catch (PropagateResponseException $e) {
+            // This exception is expected and not part of this test.
+            // It serves to prevent rendering the view.
+        }
+
+        /** @var Export $export */
+        $export = $this->exportControllerMock->_get('export');
+        self::assertEquals($expected, $export->getExcludeMap());
+    }
+
     /**
      * @test
      */
-- 
GitLab