[FEATURE] Add closure support for t3lib_div::callUserFunction
authorTolleiv Nietsch <info@tolleiv.de>
Wed, 2 May 2012 21:14:31 +0000 (23:14 +0200)
committerHelmut Hummel <helmut.hummel@typo3.org>
Wed, 1 Aug 2012 22:01:54 +0000 (00:01 +0200)
Adds the very handy option to use closures for the user functions.

Change-Id: Iae2278c4d5d988eb0e882f575d0f2d441c238213
Resolves: #36784
Releases: 6.0
Reviewed-on: http://review.typo3.org/10941
Reviewed-by: Jochen Rau
Tested-by: Jochen Rau
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
t3lib/class.t3lib_div.php
tests/Unit/t3lib/class.t3lib_divTest.php

index 674db0e..039bf67 100644 (file)
@@ -4200,7 +4200,7 @@ final class t3lib_div {
         * Calls a user-defined function/method in class
         * Such a function/method should look like this: "function proc(&$params, &$ref) {...}"
         *
         * Calls a user-defined function/method in class
         * Such a function/method should look like this: "function proc(&$params, &$ref) {...}"
         *
-        * @param string $funcName Function/Method reference, '[file-reference":"]["&"]class/function["->"method-name]'. You can prefix this reference with "[file-reference]:" and t3lib_div::getFileAbsFileName() will then be used to resolve the filename and subsequently include it by "require_once()" which means you don't have to worry about including the class file either! Example: "EXT:realurl/class.tx_realurl.php:&tx_realurl->encodeSpURL". Finally; you can prefix the class name with "&" if you want to reuse a former instance of the same object call ("singleton").
+        * @param string $funcName Function/Method reference or Closure, '[file-reference":"]["&"]class/function["->"method-name]'. You can prefix this reference with "[file-reference]:" and t3lib_div::getFileAbsFileName() will then be used to resolve the filename and subsequently include it by "require_once()" which means you don't have to worry about including the class file either! Example: "EXT:realurl/class.tx_realurl.php:&tx_realurl->encodeSpURL". Finally; you can prefix the class name with "&" if you want to reuse a former instance of the same object call ("singleton").
         * @param mixed $params Parameters to be pass along (typically an array) (REFERENCE!)
         * @param mixed $ref Reference to be passed along (typically "$this" - being a reference to the calling object) (REFERENCE!)
         * @param string $checkPrefix Not used anymore since 6.0
         * @param mixed $params Parameters to be pass along (typically an array) (REFERENCE!)
         * @param mixed $ref Reference to be passed along (typically "$this" - being a reference to the calling object) (REFERENCE!)
         * @param string $checkPrefix Not used anymore since 6.0
@@ -4211,6 +4211,11 @@ final class t3lib_div {
        public static function callUserFunction($funcName, &$params, &$ref, $checkPrefix = '', $errorMode = 0) {
                $content = FALSE;
 
        public static function callUserFunction($funcName, &$params, &$ref, $checkPrefix = '', $errorMode = 0) {
                $content = FALSE;
 
+                       // Check if we're using a closure and invoke it directly.
+               if (is_object($funcName) && is_a($funcName, 'Closure')) {
+                       return call_user_func_array($funcName, array(&$params, &$ref));
+               }
+
                        // Check persistent object and if found, call directly and exit.
                if (is_array($GLOBALS['T3_VAR']['callUserFunction'][$funcName])) {
                        return call_user_func_array(
                        // Check persistent object and if found, call directly and exit.
                if (is_array($GLOBALS['T3_VAR']['callUserFunction'][$funcName])) {
                        return call_user_func_array(
@@ -5321,4 +5326,4 @@ final class t3lib_div {
        }
 }
 
        }
 }
 
-?>
\ No newline at end of file
+?>
index 03512e1..3434513 100644 (file)
@@ -4085,6 +4085,7 @@ class t3lib_divTest extends tx_phpunit_testcase {
                $inputData = array('foo' => 'bar');
                t3lib_div::callUserFunction($functionName, $inputData, $this, 'user_', 2);
        }
                $inputData = array('foo' => 'bar');
                t3lib_div::callUserFunction($functionName, $inputData, $this, 'user_', 2);
        }
+
        /**
         * Data provider for callUserFunctionInvalidParameterDataprovider and
         * callUserFunctionWillThrowExceptionForInvalidParameters.
        /**
         * Data provider for callUserFunctionInvalidParameterDataprovider and
         * callUserFunctionWillThrowExceptionForInvalidParameters.
@@ -4161,6 +4162,20 @@ class t3lib_divTest extends tx_phpunit_testcase {
                $params['called'][spl_object_hash($this)]++;
        }
 
                $params['called'][spl_object_hash($this)]++;
        }
 
+       /**
+        * @test
+        */
+       public function callUserFunctionAcceptsClosures() {
+               $inputData = array('foo' => 'bar');
+               $closure = function($parameters, $reference) use($inputData) {
+                       $reference->assertEquals($inputData, $parameters, 'Passed data doesn\'t match expected output');
+                       return 'Worked fine';
+               };
+
+               $this->assertEquals('Worked fine', t3lib_div::callUserFunction($closure, $inputData, $this));
+       }
+
+
        ///////////////////////////////////////////////////
        // Tests concerning hasValidClassPrefix
        ///////////////////////////////////////////////////
        ///////////////////////////////////////////////////
        // Tests concerning hasValidClassPrefix
        ///////////////////////////////////////////////////