[BUGFIX] Fix check of radio buttons with itemsProcFunc 67/25867/6
authorAndreas Wolf <andreas.wolf@typo3.org>
Thu, 16 Jul 2015 23:26:46 +0000 (01:26 +0200)
committerAndreas Wolf <andreas.wolf@typo3.org>
Fri, 17 Jul 2015 13:31:39 +0000 (15:31 +0200)
Fix the value check of radio buttons if the item comes from an
itemsProcFunc by accepting the value, if it did not match with one in
the items-array before.

Change-Id: I970a0c0f20ca3d93a5ff31f094afe51a64d851dc
Resolves: #53928
Releases: master, 6.2
Reviewed-on: http://review.typo3.org/25867
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/Regular/CheckValueTest.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/Classes/Tca/RadioElementItems.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/ext_tables.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/ext_tables.sql

index 7f6aaba..869f1ce 100644 (file)
@@ -1700,7 +1700,7 @@ class DataHandler {
                                $res = $this->checkValueForCheck($res, $value, $tcaFieldConf, $table, $id, $realPid, $field);
                                break;
                        case 'radio':
-                               $res = $this->checkValueForRadio($res, $value, $tcaFieldConf);
+                               $res = $this->checkValueForRadio($res, $value, $tcaFieldConf, $table, $id, $realPid, $field);
                                break;
                        case 'group':
                        case 'select':
@@ -1929,7 +1929,8 @@ class DataHandler {
         */
        public function checkValue_radio($res, $value, $tcaFieldConf, $PP) {
                GeneralUtility::logDeprecatedFunction();
-               return $this->checkValueForRadio($res, $value, $tcaFieldConf);
+               // TODO find a way to get the field name; it should not be set in $recFID as this is only created for some record types, see checkValue()
+               return $this->checkValueForRadio($res, $value, $tcaFieldConf, $PP[0], $PP[1], $PP[4], '');
        }
 
        /**
@@ -1938,9 +1939,13 @@ class DataHandler {
         * @param array $res The result array. The processed value (if any!) is set in the 'value' key.
         * @param string $value The value to set.
         * @param array $tcaFieldConf Field configuration from TCA
+        * @param array $table The table of the record
+        * @param int $id The id of the record
+        * @param int $pid The pid of the record
+        * @param string $field The field to check
         * @return array Modified $res array
         */
-       protected function checkValueForRadio($res, $value, $tcaFieldConf) {
+       protected function checkValueForRadio($res, $value, $tcaFieldConf, $table, $id, $pid, $field) {
                if (is_array($tcaFieldConf['items'])) {
                        foreach ($tcaFieldConf['items'] as $set) {
                                if ((string)$set[1] === (string)$value) {
@@ -1949,6 +1954,21 @@ class DataHandler {
                                }
                        }
                }
+
+               // if no value was found and an itemsProcFunc is defined, check that for the value
+               if ($tcaFieldConf['itemsProcFunc'] && empty($res['value'])) {
+                       $processingService = GeneralUtility::makeInstance(ItemProcessingService::class);
+                       $processedItems = $processingService->getProcessingItems($table, $pid, $field, $this->checkValue_currentRecord,
+                               $tcaFieldConf, $tcaFieldConf['items']);
+
+                       foreach ($processedItems as $set) {
+                               if ((string)$set[1] === (string)$value) {
+                                       $res['value'] = $value;
+                                       break;
+                               }
+                       }
+               }
+
                return $res;
        }
 
diff --git a/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php b/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php
new file mode 100644 (file)
index 0000000..a1cbcfe
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+namespace TYPO3\CMS\Core\DataHandling;
+
+use TYPO3\CMS\Backend\Form\DataPreprocessor;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+
+/**
+ * Provides services around item processing
+ */
+class ItemProcessingService {
+
+       /**
+        * Executes an itemsProcFunc if defined in TCA and returns the combined result (predefined + processed items)
+        *
+        * @param string $table
+        * @param int $pageId
+        * @param string $field
+        * @param array $row
+        * @param array $tcaConfig The TCA configuration of $field
+        * @param array $selectedItems The items already defined in the TCA configuration
+        * @return array The processed items (including the predefined items)
+        */
+       public function getProcessingItems($table, $pageId, $field, $row, $tcaConfig, $selectedItems) {
+               $pageId = $table === 'pages' ? $row['uid'] : $row['pid'];
+
+               $TSconfig = BackendUtility::getPagesTSconfig($pageId);
+               $fieldTSconfig = $TSconfig['TCEFORM.'][$table . '.'][$field . '.'];
+
+               $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class);
+               $items = $dataPreprocessor->procItems(
+                       $selectedItems,
+                       $fieldTSconfig['itemsProcFunc.'],
+                       $tcaConfig,
+                       $table,
+                       $row,
+                       $field
+               );
+
+               return $items;
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/CheckValueTest.php b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/CheckValueTest.php
new file mode 100644 (file)
index 0000000..3a0cfa0
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase;
+
+
+/**
+ * Tests related to DataHandler::checkValue()
+ */
+class CheckValueTest extends AbstractDataHandlerActionTestCase {
+
+       /**
+        * @var string
+        */
+       protected $scenarioDataSetDirectory = 'typo3/sysext/core/Tests/Functional/DataHandling/Regular/DataSet/';
+
+       protected function setUp() {
+               $this->testExtensionsToLoad[] = 'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler';
+
+               parent::setUp();
+               $this->importScenarioDataSet('LiveDefaultPages');
+       }
+
+
+       /**
+        * @test
+        */
+       public function radioButtonValueMustBeDefinedInTcaItems() {
+               $record = $this->insertRecordWithRadioFieldValue('predefined value');
+
+               $this->assertEquals('predefined value', $record['tx_testdatahandler_radio']);
+       }
+
+       /**
+        * @test
+        */
+       public function radioButtonValueMustComeFromItemsProcFuncIfNotDefinedInTcaItems() {
+               $record = $this->insertRecordWithRadioFieldValue('processed value');
+
+               $this->assertEquals('processed value', $record['tx_testdatahandler_radio']);
+       }
+
+       /**
+        * @test
+        */
+       public function radioButtonValueIsNotSavedIfNotDefinedInTcaItemsOrProcessingItems() {
+               $record = $this->insertRecordWithRadioFieldValue('some other value');
+
+               $this->assertEquals('', $record['tx_testdatahandler_radio']);
+       }
+
+       /**
+        * @return array
+        */
+       protected function insertRecordWithRadioFieldValue($value) {
+               // pid 88 comes from LiveDefaultPages
+               $result = $this->actionService->createNewRecord('tt_content', 88, array(
+                       'tx_testdatahandler_radio' => $value
+               ));
+               $recordUid = $result['tt_content'][0];
+
+               $record = BackendUtility::getRecord('tt_content', $recordUid);
+
+               return $record;
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/Classes/Tca/RadioElementItems.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/Classes/Tca/RadioElementItems.php
new file mode 100644 (file)
index 0000000..c4c88c2
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+namespace TYPO3\TestDatahandler\Classes\Tca;
+
+/**
+ * Items processor for radio buttons for the functional tests of DataHandler::checkValue()
+ */
+class RadioElementItems {
+
+       /**
+        * @return array
+        */
+       public function getItems($params) {
+               $params['items'][] = array('processed label', 'processed value');
+       }
+
+}
index 8064db9..dc0165f 100644 (file)
@@ -29,6 +29,17 @@ defined('TYPO3_MODE') or die();
                                'autoSizeMax' => '10',
                        ),
                ),
+                'tx_testdatahandler_radio' => array(
+                       'exclude' => 1,
+                       'label' => 'DataHandler Test Radio',
+                       'config' => array(
+                               'type' => 'radio',
+                               'items' => array(
+                                       array('predefined label', 'predefined value')
+                               ),
+                               'itemsProcFunc' => 'TYPO3\TestDatahandler\Classes\Tca\RadioElementItems->getItems'
+                       ),
+               ),
        )
 );
 
index a572526..99c6c99 100644 (file)
@@ -3,7 +3,8 @@
 #
 CREATE TABLE tt_content (
     tx_testdatahandler_select text NOT NULL,
-    tx_testdatahandler_group text NOT NULL
+    tx_testdatahandler_group text NOT NULL,
+    tx_testdatahandler_radio text NOT NULL
 );
 
 #