[BUGFIX] Reallow '0' as valid userFunc argument in TypoScript 27/46427/2
authorGernot Leitgab <office@leitgab.at>
Mon, 25 Jan 2016 18:13:24 +0000 (19:13 +0100)
committerFrank Naegler <frank.naegler@typo3.org>
Mon, 1 Feb 2016 12:39:46 +0000 (13:39 +0100)
With #47301 the parsing of userFunc in TypoScript has changed.
The change prevents '0' as valid argument.

This patch fix the '0' bug but also adds some new unit tests.
The parser method also includes a bug with quoted values which are not the
last argument. this bug is now fixed too.

Resolves: #72936
Related: #47301
Releases: master, 7.6, 6.2
Change-Id: Ic8df6ea21642e012438dba0a6a299c15939ab119
Reviewed-on: https://review.typo3.org/46427
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
typo3/sysext/core/Classes/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcher.php
typo3/sysext/core/Tests/Unit/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcherTest.php
typo3/sysext/core/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/ConditionMatcherUserFuncs.php

index 66b8ef0..633bdbc 100644 (file)
@@ -424,7 +424,7 @@ abstract class AbstractConditionMatcher
                 $matches = array();
                 preg_match_all('/^\s*([^\(\s]+)\s*(?:\((.*)\))?\s*$/', $value, $matches);
                 $funcName = $matches[1][0];
-                $funcValues = $matches[2][0] ? $this->parseUserFuncArguments($matches[2][0]) : array();
+                $funcValues = trim($matches[2][0]) !== '' ? $this->parseUserFuncArguments($matches[2][0]) : array();
                 if (is_callable($funcName) && call_user_func_array($funcName, $funcValues)) {
                     return true;
                 }
@@ -491,11 +491,13 @@ abstract class AbstractConditionMatcher
                     $segment = preg_replace('/^(.*?[^\\\])' . $quote . '.*$/', '\1', substr($arguments, 1));
                     $segment = str_replace('\\' . $quote, $quote, $segment);
                     $result[] = $segment;
-                    $offset = strpos($arguments, ',', strlen($segment) + 2);
+                    // shorten $arguments
+                    $arguments = substr($arguments, strlen($segment) + 2);
+                    $offset = strpos($arguments, ',');
                     if ($offset === false) {
                         $offset = strlen($arguments);
                     }
-                    $arguments = substr($arguments, $offset);
+                    $arguments = substr($arguments, $offset + 1);
                 } else {
                     $result[] = trim(substr($arguments, 0, $pos));
                     $arguments = substr($arguments, $pos + 1);
index 11bbbad..13b613d 100644 (file)
@@ -225,6 +225,32 @@ class AbstractConditionMatcherTest extends UnitTestCase
     /**
      * @test
      */
+    public function testUserFuncWithIntegerZeroArgument()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithSingleArgument(0)')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithWhitespaceArgument()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithNoArgument( )')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
     public function testUserFuncWithMultipleArguments()
     {
         $this->assertTrue(
@@ -238,6 +264,188 @@ class AbstractConditionMatcherTest extends UnitTestCase
     /**
      * @test
      */
+    public function testUserFuncWithMultipleDifferentArgumentsNullBoolString()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments(0,true,"foo")')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsNullStringBool()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments(0,"foo",true)')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsStringBoolNull()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments("foo",true,0)')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsStringNullBool()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments("foo",0,true)')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsBoolNullString()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments(true,0,"foo")')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsBoolStringNull()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments(true,"foo",0)')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsNullBoolStringSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments(0,true,'foo')")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsNullStringBoolSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments(0,'foo',true)")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsStringBoolNullSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments('foo',true,0)")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsStringNullBoolSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments('foo',0,true)")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsBoolNullStringSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments(true,0,'foo')")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleDifferentArgumentsBoolStringNullSingleQuotes()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments(true,'foo',0)")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleSingleQuotedArguments()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', "user_testFunctionWithThreeArguments('foo','bar', 'baz')")
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testUserFuncWithMultipleSoubleQuotedArguments()
+    {
+        $this->assertTrue(
+            $this->evaluateConditionCommonMethod->invokeArgs(
+                $this->conditionMatcher,
+                array('userFunc', 'user_testFunctionWithThreeArguments("foo","bar","baz")')
+            )
+        );
+    }
+
+    /**
+     * @test
+     */
     public function testUserFuncReturnsFalse()
     {
         $this->assertFalse(
index 0e45078..174ec34 100644 (file)
  */
 
 namespace {
+    function user_testFunctionWithNoArgument()
+    {
+        return count(func_get_args()) === 0;
+    }
+
     function user_testFunctionWithSingleArgument()
     {
         return count(func_get_args()) === 1;