[FEATURE] Support multiple display conditions in TCA
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / ElementConditionMatcher.php
index 8a439aa..1e3c48d 100644 (file)
@@ -43,6 +43,77 @@ class ElementConditionMatcher {
         */
        protected $record = array();
 
+       /**
+        * Evaluates the provided condition and returns TRUE if the form
+        * element should be displayed.
+        *
+        * The condition string is separated by colons and the first part
+        * indicates what type of evaluation should be performed.
+        *
+        * @param string $displayCondition
+        * @param array $record
+        * @param string $flexformValueKey
+        * @param integer $recursionLevel Internal level of recursion
+        * @return boolean TRUE if condition evaluates successfully
+        */
+       public function match($displayCondition, array $record = array(), $flexformValueKey = '', $recursionLevel = 0) {
+               if ($recursionLevel > 99) {
+                       // This should not happen, treat as misconfiguration
+                       return TRUE;
+               }
+               if (!is_array($displayCondition)) {
+                       // DisplayCondition is not an array - just get its value
+                       $result = $this->matchSingle($displayCondition, $record, $flexformValueKey);
+               } else {
+                       // Multiple conditions given as array ('AND|OR' => condition array)
+                       $conditionEvaluations = array(
+                               'AND' => array(),
+                               'OR' => array(),
+                       );
+                       foreach ($displayCondition as $logicalOperator => $groupedDisplayConditions) {
+                               $logicalOperator = strtoupper($logicalOperator);
+                               if (($logicalOperator !== 'AND' && $logicalOperator !== 'OR') || !is_array($groupedDisplayConditions)) {
+                                       // Invalid line. Skip it.
+                                       continue;
+                               } else {
+                                       foreach ($groupedDisplayConditions as $key => $singleDisplayCondition) {
+                                               $key = strtoupper($key);
+                                               if (($key === 'AND' || $key === 'OR') && is_array($singleDisplayCondition)) {
+                                                       // Recursion statement: condition is 'AND' or 'OR' and is pointing to an array (should be conditions again)
+                                                       $conditionEvaluations[$logicalOperator][] = $this->match(
+                                                               array($key => $singleDisplayCondition),
+                                                               $record,
+                                                               $flexformValueKey,
+                                                               $recursionLevel + 1
+                                                       );
+                                               } else {
+                                                       // Condition statement: collect evaluation of this single condition.
+                                                       $conditionEvaluations[$logicalOperator][] = $this->matchSingle(
+                                                               $singleDisplayCondition,
+                                                               $record,
+                                                               $flexformValueKey
+                                                       );
+                                               }
+                                       }
+                               }
+                       }
+                       if (count($conditionEvaluations['OR']) > 0 && in_array(TRUE, $conditionEvaluations['OR'], TRUE)) {
+                               // There are OR conditions and at least one of them is TRUE
+                               $result = TRUE;
+                       } elseif (count($conditionEvaluations['AND']) > 0 && !in_array(FALSE, $conditionEvaluations['AND'], TRUE)) {
+                               // There are AND conditions and none of them is FALSE
+                               $result = TRUE;
+                       } elseif (count($conditionEvaluations['OR']) > 0 || count($conditionEvaluations['AND']) > 0) {
+                               // There are some conditions. But no OR was TRUE and at least one AND was FALSE
+                               $result = FALSE;
+                       } else {
+                               // There are no proper conditions - misconfiguration. Return TRUE.
+                               $result = TRUE;
+                       }
+               }
+               return $result;
+       }
+
        /**
         * Evaluates the provided condition and returns TRUE if the form
         * element should be displayed.
@@ -54,8 +125,9 @@ class ElementConditionMatcher {
         * @param array $record
         * @param string $flexformValueKey
         * @return boolean
+        * @see match()
         */
-       public function match($displayCondition, array $record = array(), $flexformValueKey = '') {
+       protected function matchSingle($displayCondition, array $record = array(), $flexformValueKey = '') {
                $this->record = $record;
                $this->flexformValueKey = $flexformValueKey;
                $result = FALSE;