[FEATURE] Custom TypoScript-conditions also in backend 68/35068/7
authorStefan Neufeind <typo3.neufeind@speedpartner.de>
Mon, 8 Dec 2014 23:44:17 +0000 (00:44 +0100)
committerBenjamin Mack <benni@typo3.org>
Fri, 2 Jan 2015 19:38:36 +0000 (20:38 +0100)
Make the feature for custom TypoScript-conditions available
in both frontend (was already there) and backend (new) by
moving it to the AbstractConditionMatcher.

Resolves: #63600
Related: #61489
Releases: master
Change-Id: I653f8cca53b23f6c16d81ed5ea3f2bc853e98a2e
Reviewed-on: http://review.typo3.org/35068
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
typo3/sysext/backend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php [new file with mode: 0644]
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Configuration/TypoScript/ConditionMatching/AbstractCondition.php
typo3/sysext/core/Classes/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcher.php
typo3/sysext/core/Documentation/Changelog/master/Feature-63600-CustomTypoScriptConditionsInBackend.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php

index c2afb79..1d6c19a 100644 (file)
@@ -88,6 +88,11 @@ class ConditionMatcher extends AbstractConditionMatcher {
                                                }
                                        }
                                        break;
+                               default:
+                                       $conditionResult = parent::evaluateCustomDefinedCondition($string);
+                                       if ($conditionResult !== NULL) {
+                                               return $conditionResult;
+                                       }
                        }
                }
                return FALSE;
index e978a76..ac85246 100644 (file)
@@ -998,4 +998,11 @@ class ConditionMatcherTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                }
        }
 
+       /**
+        * @test
+        * @expectedException \TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException
+        */
+       public function matchCallsTestConditionAndHandsOverParameters() {
+               $this->matchCondition->match('[TYPO3\\CMS\\Backend\\Tests\\Unit\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
+       }
 }
diff --git a/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php b/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php
new file mode 100644 (file)
index 0000000..ae29b1c
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Fixture for custom conditions
+ */
+class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition {
+
+       /**
+        * Test matcher tests input parameters.
+        *
+        * @param array $conditionParameters
+        * @throws TestConditionException
+        * @return bool
+        */
+       public function matchCondition(array $conditionParameters) {
+               // Throw an exception if everything is fine, this exception is *expected* in the according unit test
+               if ($conditionParameters[0] === '= 7' && $conditionParameters[1] === '!= 6') {
+                       throw new TestConditionException('All Ok', 1411581139);
+               }
+       }
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php b/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php
new file mode 100644 (file)
index 0000000..b8e9f67
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Exception thrown by TestCondition
+ */
+class TestConditionException extends \Exception {
+}
\ No newline at end of file
index c82b673..483d729 100644 (file)
@@ -22,19 +22,19 @@ namespace TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching;
 abstract class AbstractCondition {
 
        /**
-        * @var \TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher
+        * @var \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher
         */
        protected $conditionMatcherInstance;
 
        /**
-        * @return \TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher
+        * @return \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher
         */
        protected function getConditionMatcherInstance() {
                return $this->conditionMatcherInstance;
        }
 
        /**
-        * @param \TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher $conditionMatcherInstance
+        * @param \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher $conditionMatcherInstance
         */
        public function setConditionMatcherInstance($conditionMatcherInstance) {
                $this->conditionMatcherInstance = $conditionMatcherInstance;
index 9fabceb..8493c50 100644 (file)
@@ -427,6 +427,40 @@ abstract class AbstractConditionMatcher {
        }
 
        /**
+        * Evaluates a TypoScript condition given as input with a custom class name,
+        * e.g. "[MyCompany\MyPackage\ConditionMatcher\MyOwnConditionMatcher = myvalue]"
+        *
+        * @param string $condition The condition to match
+        * @return NULL|boolean Result of the evaluation; NULL if condition could not be evaluated
+        * @throws \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
+        */
+       protected function evaluateCustomDefinedCondition($condition) {
+               $conditionResult = NULL;
+
+               list($conditionClassName, $conditionParameters) = GeneralUtility::trimExplode(' ', $condition, FALSE, 2);
+
+               // Check if the condition class name is a valid class
+               // This is necessary to not stop here for the conditions ELSE and GLOBAL
+               if (class_exists($conditionClassName)) {
+                       // Use like this: [MyCompany\MyPackage\ConditionMatcher\MyOwnConditionMatcher = myvalue]
+                       /** @var \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition $conditionObject */
+                       $conditionObject = GeneralUtility::makeInstance($conditionClassName);
+                       if (($conditionObject instanceof \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition) === FALSE) {
+                               throw new \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException(
+                                       '"' . $conditionClassName . '" is not a valid TypoScript Condition object.',
+                                       1410286153
+                               );
+                       }
+
+                       $conditionParameters = $this->parseUserFuncArguments($conditionParameters);
+                       $conditionObject->setConditionMatcherInstance($this);
+                       $conditionResult = $conditionObject->matchCondition($conditionParameters);
+               }
+
+               return $conditionResult;
+       }
+
+       /**
         * Parses arguments to the userFunc.
         *
         * @param string $arguments
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-63600-CustomTypoScriptConditionsInBackend.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-63600-CustomTypoScriptConditionsInBackend.rst
new file mode 100644 (file)
index 0000000..f90ac65
--- /dev/null
@@ -0,0 +1,33 @@
+====================================================================
+Feature: #61489 - Allow own TypoScript Conditions in Backend as well
+====================================================================
+
+Description
+===========
+
+It is now possible to add own TypoScript conditions via a separate API in the Backend. The API for the frontend
+was introduced with TYPO3 CMS 7.0.
+
+An extension / package can now ship an implementation of a new abstract class AbstractCondition. Via the existing
+TypoScript Condition Syntax the class is called by the simple full namespaced class name.
+The class's main function "matchCondition" can flexibly evaluate any parameters given after the class name.
+
+Usage:
+
+.. code-block:: typoscript
+
+       [BigCompanyName\TypoScriptLovePackage\MyCustomTypoScriptCondition]
+
+       [BigCompanyName\TypoScriptLovePackage\MyCustomTypoScriptCondition = 7]
+
+       [BigCompanyName\TypoScriptLovePackage\MyCustomTypoScriptCondition = 7, != 6]
+
+       [BigCompanyName\TypoScriptLovePackage\MyCustomTypoScriptCondition = {$mysite.myconstant}]
+
+where the TypoScript Condition class deals with =/!= etc itself.
+
+Impact
+======
+
+If you've previously used the "userFunc" condition, you are encouraged to use this new API for your own TypoScript
+conditions.
index f24a177..1db9041 100644 (file)
@@ -79,24 +79,9 @@ class ConditionMatcher extends AbstractConditionMatcher {
                                        }
                                        break;
                                default:
-                                       list($conditionClassName, $conditionParameters) = GeneralUtility::trimExplode(' ', $string, FALSE, 2);
-
-                                       // Check if the condition class name is a valid class
-                                       // This is necessary to not stop here for the conditions ELSE and GLOBAL
-                                       if (class_exists($conditionClassName)) {
-                                               // Use like this: [MyCompany\MyPackage\ConditionMatcher\MyOwnConditionMatcher = myvalue]
-                                               /** @var \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition $conditionObject */
-                                               $conditionObject = GeneralUtility::makeInstance($conditionClassName);
-                                               if (($conditionObject instanceof \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition) === FALSE) {
-                                                       throw new \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException(
-                                                               '"' . $key . '" is not a valid TypoScript Condition object.',
-                                                               1410286153
-                                                       );
-                                               }
-
-                                               $conditionParameters = $this->parseUserFuncArguments($conditionParameters);
-                                               $conditionObject->setConditionMatcherInstance($this);
-                                               return $conditionObject->matchCondition($conditionParameters);
+                                       $conditionResult = parent::evaluateCustomDefinedCondition($string);
+                                       if ($conditionResult !== NULL) {
+                                               return $conditionResult;
                                        }
                        }
                }
index e11ebdc..ae05cd8 100644 (file)
@@ -23,7 +23,7 @@ class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMa
         * Test matcher tests input parameters.
         *
         * @param array $conditionParameters
-        * @throws \RuntimeException
+        * @throws TestConditionException
         * @return bool
         */
        public function matchCondition(array $conditionParameters) {