[FEATURE] Add maximumRecords evaluation for TCA type 'check' 46/26946/9
authorOliver Hader <oliver@typo3.org>
Mon, 20 Jan 2014 18:09:21 +0000 (19:09 +0100)
committerBenjamin Mack <benni@typo3.org>
Sun, 2 Feb 2014 13:27:21 +0000 (14:27 +0100)
Allow the max items evaluation for checkboxes by setting the
accordant 'eval' property in the field configuration in TCA.

This makes it possible to have only e.g. 5 records that have a
checkbox set system-wide or PID-wide. If an editor
sets a another checkbox in record #6, it gets reverted
until another record was unchecked.

Parameters are "maximumRecordsChecked" and
"maximumRecordsCheckedInPid".

$tcaFieldConf = array(
'type' => 'check',
'eval' => 'maximumRecordsChecked',
'validation' => array(
 'maximumRecordsChecked' => 5
)
);

Change-Id: Ic33571fec15dcc9f83a61e2409256cce7dae8b12
Documentation: #55188
Resolves: #55187
Releases: 6.2
Reviewed-on: https://review.typo3.org/26946
Reviewed-by: Ingo Schmitt
Tested-by: Ingo Schmitt
Reviewed-by: Frans Saris
Tested-by: Frans Saris
typo3/sysext/core/Classes/DataHandling/DataHandler.php

index 6757b39..f0d8ff8 100644 (file)
@@ -1578,7 +1578,7 @@ class DataHandler {
                                $res = $this->checkValue_input($res, $value, $tcaFieldConf, $PP, $field);
                                break;
                        case 'check':
-                               $res = $this->checkValue_check($res, $value, $tcaFieldConf, $PP);
+                               $res = $this->checkValue_check($res, $value, $tcaFieldConf, $PP, $field);
                                break;
                        case 'radio':
                                $res = $this->checkValue_radio($res, $value, $tcaFieldConf, $PP);
@@ -1687,10 +1687,11 @@ class DataHandler {
         * @param string $value The value to set.
         * @param array $tcaFieldConf Field configuration from TCA
         * @param array $PP Additional parameters in a numeric array: $table,$id,$curValue,$status,$realPid,$recFID
+        * @param string $field Field name
         * @return array Modified $res array
         * @todo Define visibility
         */
-       public function checkValue_check($res, $value, $tcaFieldConf, $PP) {
+       public function checkValue_check($res, $value, $tcaFieldConf, $PP, $field = '') {
                list($table, $id, $curValue, $status, $realPid, $recFID) = $PP;
                $itemC = count($tcaFieldConf['items']);
                if (!$itemC) {
@@ -1703,6 +1704,25 @@ class DataHandler {
                if ($value > $maxV) {
                        $value = $maxV;
                }
+               if ($field && $realPid >= 0 && $value > 0 && !empty($tcaFieldConf['eval'])) {
+                       $evalCodesArray = GeneralUtility::trimExplode(',', $tcaFieldConf['eval'], TRUE);
+                       $otherRecordsWithSameValue = array();
+                       $maxCheckedRecords = 0;
+                       if (in_array('maximumRecordsCheckedInPid', $evalCodesArray)) {
+                               $otherRecordsWithSameValue = $this->getRecordsWithSameValue($table, $id, $field, $value, $realPid);
+                               $maxCheckedRecords = (int)$tcaFieldConf['validation']['maximumRecordsCheckedInPid'];
+                       }
+                       if (in_array('maximumRecordsChecked', $evalCodesArray)) {
+                               $otherRecordsWithSameValue = $this->getRecordsWithSameValue($table, $id, $field, $value);
+                               $maxCheckedRecords = (int)$tcaFieldConf['validation']['maximumRecordsChecked'];
+                       }
+
+                       // there are more than enough records with value "1" in the DB
+                       // if so, set this value to "0" again
+                       if ($maxCheckedRecords && count($otherRecordsWithSameValue) >= $maxCheckedRecords) {
+                               $value = 0;
+                       }
+               }
                $res['value'] = $value;
                return $res;
        }
@@ -2376,6 +2396,29 @@ class DataHandler {
        }
 
        /**
+        * gets all records that have the same value in a field
+        * excluding the given uid
+        *
+        * @param string $tableName Table name
+        * @param integer $uid UID to filter out in the lookup (the record itself...)
+        * @param string $fieldName Field name for which $value must be unique
+        * @param string $value Value string.
+        * @param integer $pageId If set, the value will be unique for this PID
+        * @return array
+        */
+       public function getRecordsWithSameValue($tableName, $uid, $fieldName, $value, $pageId = 0) {
+               $result = array();
+               if (!empty($GLOBALS['TCA'][$tableName]['columns'][$fieldName])) {
+
+                       $uid = (int)$uid;
+                       $pageId = (int)$pageId;
+                       $whereStatement = ' AND uid <> ' . $uid . ' AND ' . ($pageId ? 'pid = ' . $pageId : 'pid >= 0');
+                       $result = BackendUtility::getRecordsByField($tableName, $fieldName, $value, $whereStatement);
+               }
+               return $result;
+       }
+
+       /**
         * @param string $value The field value to be evaluated
         * @param array $evalArray Array of evaluations to traverse.
         * @param string $is_in The "is_in" value of the field configuration from TCA