[BUGFIX] Allow colon in last "displayCond" part 52/20552/5
authorSascha Egerer <sascha.egerer@dkd.de>
Mon, 6 May 2013 16:03:24 +0000 (18:03 +0200)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Mon, 22 Jul 2013 17:55:34 +0000 (19:55 +0200)
Explode the "displayCond"-string just to required
number of parts. So the last part can also contain colons.

Also backports unit-tests from ElementConditionMatcher of
TYPO3 6.1 and adds a check for this colon-bugfix here.

Resolves: #47988
Releases: 6.0, 4.7, 4.5
Change-Id: I940e17ea346dda91607573406fd83d919d83e36a
Reviewed-on: https://review.typo3.org/20552
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
typo3/sysext/backend/Classes/Form/FormEngine.php
typo3/sysext/backend/Tests/Unit/Form/FormEngineTest.php [new file with mode: 0644]

index f298218..25a4c7d 100644 (file)
@@ -5959,84 +5959,87 @@ function ' . $evalData . '(value) {
         */
        public function isDisplayCondition($displayCond, $row, $ffValueKey = '') {
                $output = FALSE;
-               $parts = explode(':', $displayCond);
+               list($matchType, $condition) = explode(':', $displayCond, 2);
                // Type of condition:
-               switch ((string) $parts[0]) {
+               switch ((string) $matchType) {
                case 'FIELD':
+                       list($fieldName, $operator, $operand) = explode(':', $condition, 3);
                        if ($ffValueKey) {
-                               if (strpos($parts[1], 'parentRec.') !== FALSE) {
-                                       $fParts = explode('.', $parts[1]);
+                               if (strpos($fieldName, 'parentRec.') !== FALSE) {
+                                       $fParts = explode('.', $fieldName);
                                        $theFieldValue = $row['parentRec'][$fParts[1]];
                                } else {
-                                       $theFieldValue = $row[$parts[1]][$ffValueKey];
+                                       $theFieldValue = $row[$fieldName][$ffValueKey];
                                }
                        } else {
-                               $theFieldValue = $row[$parts[1]];
+                               $theFieldValue = $row[$fieldName];
                        }
-                       switch ((string) $parts[2]) {
+                       switch ((string) $operator) {
                        case 'REQ':
-                               if (strtolower($parts[3]) == 'true') {
+                               if (strtolower($operand) == 'true') {
                                        $output = $theFieldValue ? TRUE : FALSE;
-                               } elseif (strtolower($parts[3]) == 'false') {
+                               } elseif (strtolower($operand) == 'false') {
                                        $output = !$theFieldValue ? TRUE : FALSE;
                                }
                                break;
                        case '>':
-                               $output = $theFieldValue > $parts[3];
+                               $output = $theFieldValue > $operand;
                                break;
                        case '<':
-                               $output = $theFieldValue < $parts[3];
+                               $output = $theFieldValue < $operand;
                                break;
                        case '>=':
-                               $output = $theFieldValue >= $parts[3];
+                               $output = $theFieldValue >= $operand;
                                break;
                        case '<=':
-                               $output = $theFieldValue <= $parts[3];
+                               $output = $theFieldValue <= $operand;
                                break;
                        case '-':
 
                        case '!-':
-                               $cmpParts = explode('-', $parts[3]);
+                               $cmpParts = explode('-', $operand);
                                $output = $theFieldValue >= $cmpParts[0] && $theFieldValue <= $cmpParts[1];
-                               if ($parts[2][0] == '!') {
+                               if ($operator[0] == '!') {
                                        $output = !$output;
                                }
                                break;
                        case 'IN':
 
                        case '!IN':
-                               $output = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($parts[3], $theFieldValue);
-                               if ($parts[2][0] == '!') {
+                               $output = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($operand, $theFieldValue);
+                               if ($operator[0] == '!') {
                                        $output = !$output;
                                }
                                break;
                        case '=':
 
                        case '!=':
-                               $output = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($parts[3], $theFieldValue);
-                               if ($parts[2][0] == '!') {
+                               $output = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($operand, $theFieldValue);
+                               if ($operator[0] == '!') {
                                        $output = !$output;
                                }
                                break;
                        }
                        break;
                case 'EXT':
-                       switch ((string) $parts[2]) {
+                       list($extensionKey, $operator, $operand) = explode(':', $condition, 3);
+                       switch ((string) $operator) {
                        case 'LOADED':
-                               if (strtolower($parts[3]) == 'true') {
-                                       $output = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($parts[1]) ? TRUE : FALSE;
-                               } elseif (strtolower($parts[3]) == 'false') {
-                                       $output = !\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($parts[1]) ? TRUE : FALSE;
+                               if (strtolower($operand) == 'true') {
+                                       $output = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey) ? TRUE : FALSE;
+                               } elseif (strtolower($operand) == 'false') {
+                                       $output = !\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey) ? TRUE : FALSE;
                                }
                                break;
                        }
                        break;
                case 'REC':
-                       switch ((string) $parts[1]) {
+                       list($operator, $operand) = explode(':', $condition, 2);
+                       switch ((string) $operator) {
                        case 'NEW':
-                               if (strtolower($parts[2]) == 'true') {
+                               if (strtolower($operand) == 'true') {
                                        $output = !(intval($row['uid']) > 0) ? TRUE : FALSE;
-                               } elseif (strtolower($parts[2]) == 'false') {
+                               } elseif (strtolower($operand) == 'false') {
                                        $output = intval($row['uid']) > 0 ? TRUE : FALSE;
                                }
                                break;
@@ -6045,7 +6048,7 @@ function ' . $evalData . '(value) {
                case 'HIDE_L10N_SIBLINGS':
                        if ($ffValueKey === 'vDEF') {
                                $output = TRUE;
-                       } elseif ($parts[1] === 'except_admin' && $GLOBALS['BE_USER']->isAdmin()) {
+                       } elseif ($condition === 'except_admin' && $GLOBALS['BE_USER']->isAdmin()) {
                                $output = TRUE;
                        }
                        break;
@@ -6053,7 +6056,8 @@ function ' . $evalData . '(value) {
                        $output = $GLOBALS['BE_USER']->isAdmin() ? TRUE : FALSE;
                        break;
                case 'VERSION':
-                       switch ((string) $parts[1]) {
+                       list($operator, $operand) = explode(':', $condition, 2);
+                       switch ((string) $operator) {
                        case 'IS':
                                $isNewRecord = intval($row['uid']) > 0 ? FALSE : TRUE;
                                // Detection of version can be done be detecting the workspace of the user
@@ -6068,10 +6072,10 @@ function ' . $evalData . '(value) {
                                // -- if user is in workspace: always TRUE
                                // -- if editor is in live ws: only TRUE if pid == -1
                                $isVersion = ($isUserInWorkspace || $isRecordDetectedAsVersion) && !$isNewRecord;
-                               if (strtolower($parts[2]) == 'true') {
+                               if (strtolower($operand) == 'true') {
                                        $output = $isVersion;
                                } else {
-                                       if (strtolower($parts[2]) == 'false') {
+                                       if (strtolower($operand) == 'false') {
                                                $output = !$isVersion;
                                        }
                                }
diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormEngineTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormEngineTest.php
new file mode 100644 (file)
index 0000000..22f742e
--- /dev/null
@@ -0,0 +1,245 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\Form;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Sebastian Michaelsen <michaelsen@t3seo.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case
+ */
+class FormEngineTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Backend\Form\FormEngine
+        */
+       protected $fixture;
+
+       /**
+        * Sets up this test case.
+        */
+       protected function setUp() {
+               $this->fixture = new \TYPO3\CMS\Backend\Form\FormEngine();
+       }
+
+       /**
+        * Tears down this test case.
+        */
+       protected function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * Returns data sets for the test matchConditionStrings
+        * Each dataset is an array with the following elements:
+        * - the condition string
+        * - the current record
+        * - the current flexform value key
+        * - the expected result
+        *
+        * @return array
+        */
+       public function conditionStringDataProvider() {
+               return array(
+                       'Invalid condition string' => array(
+                               'xINVALIDx:',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Not loaded extension compares to loaded as FALSE' => array(
+                               'EXT:neverloadedext:LOADED:TRUE',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Not loaded extension compares to not loaded as TRUE' => array(
+                               'EXT:neverloadedext:LOADED:FALSE',
+                               array(),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Loaded extension compares to TRUE' => array(
+                               'EXT:backend:LOADED:TRUE',
+                               array(),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Loaded extension compares to FALSE' => array(
+                               'EXT:backend:LOADED:FALSE',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Field is not greater zero if not given' => array(
+                               'FIELD:uid:>:0',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Field is not equal 0 if not given' => array(
+                               'FIELD:uid:=:0',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Field value string comparison' => array(
+                               'FIELD:foo:=:bar',
+                               array('foo' => 'bar'),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Field value string comparison with colons in value' => array(
+                               'FIELD:foo:=::bar:',
+                               array('foo' => ':bar:'),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Field value comparison for required value is false for different value' => array(
+                               'FIELD:foo:REQ:FALSE',
+                               array('foo' => 'bar'),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Field value string not equal comparison' => array(
+                               'FIELD:foo:!=:baz',
+                               array('foo' => 'bar'),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Field value in range' => array(
+                               'FIELD:uid:-:3-42',
+                               array('uid' => '23'),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Field value greater than' => array(
+                               'FIELD:uid:>=:42',
+                               array('uid' => '23'),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Flexform value invalid comparison' => array(
+                               'FIELD:foo:=:bar',
+                               array(
+                                       'foo' => array(
+                                               'vDEF' => 'bar'
+                                       ),
+                               ),
+                               'vDEF',
+                               TRUE,
+                       ),
+                       'Flexform value valid comparison' => array(
+                               'FIELD:parentRec.foo:=:bar',
+                               array(
+                                       'parentRec' => array(
+                                               'foo' => 'bar'
+                                       ),
+                               ),
+                               'vDEF',
+                               TRUE,
+                       ),
+                       'Field is value for default languge without flexform' => array(
+                               'HIDE_L10N_SIBLINGS',
+                               array(),
+                               NULL,
+                               FALSE,
+                       ),
+                       'Field is value for default languge with flexform' => array(
+                               'HIDE_L10N_SIBLINGS',
+                               array(),
+                               'vDEF',
+                               TRUE,
+                       ),
+                       'Field is value for default languge with sibling' => array(
+                               'HIDE_L10N_SIBLINGS',
+                               array(),
+                               'vEN',
+                               FALSE,
+                       ),
+                       'New is TRUE for new comparison with TRUE' => array(
+                               'REC:NEW:TRUE',
+                               array('uid' => NULL),
+                               NULL,
+                               TRUE,
+                       ),
+                       'New is FALSE for new comparison with FALSE' => array(
+                               'REC:NEW:FALSE',
+                               array('uid' => NULL),
+                               NULL,
+                               FALSE,
+                       ),
+                       'New is FALSE for not new element' => array(
+                               'REC:NEW:TRUE',
+                               array('uid' => 42),
+                               NULL,
+                               FALSE,
+                       ),
+                       'New is TRUE for not new element compared to FALSE' => array(
+                               'REC:NEW:FALSE',
+                               array('uid' => 42),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Version is TRUE for versioned row' => array(
+                               'VERSION:IS:TRUE',
+                               array(
+                                       'uid' => 42,
+                                       'pid' => -1
+                               ),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Version is TRUE for not versioned row compared with FALSE' => array(
+                               'VERSION:IS:FALSE',
+                               array(
+                                       'uid' => 42,
+                                       'pid' => 1
+                               ),
+                               NULL,
+                               TRUE,
+                       ),
+                       'Version is TRUE for NULL row compared with TRUE' => array(
+                               'VERSION:IS:TRUE',
+                               array(
+                                       'uid' => NULL,
+                                       'pid' => NULL,
+                               ),
+                               NULL,
+                               FALSE,
+                       ),
+               );
+       }
+
+       /**
+        * @param string $condition
+        * @param array $record
+        * @param string $flexformValueKey
+        * @param string $expectedResult
+        * @dataProvider conditionStringDataProvider
+        * @test
+        */
+       public function matchConditionStrings($condition, array $record, $flexformValueKey, $expectedResult) {
+               $this->assertEquals($expectedResult, $this->fixture->isDisplayCondition($condition, $record, $flexformValueKey));
+       }
+}
+?>
\ No newline at end of file