dmitry Thu Jul 17 09:53:42 2008 UTC Added files: (Branch: PHP_5_3) /php-src/ext/curl/tests curl_006.phpt /php-src/ext/filter/tests callback_closure.phpt /php-src/ext/mysqli/tests mysqli_set_local_infile_handler_closures.phpt /php-src/ext/pcntl/tests signal_closure_handler.phpt /php-src/ext/session/tests save_handler_closures.inc session_set_save_handler_closures.phpt /php-src/ext/sqlite/tests sqlite_closures_001.phpt sqlite_closures_002.phpt /php-src/ext/standard/tests/assert assert_closures.phpt /php-src/ext/standard/tests/general_functions closures_001.phpt closures_002.phpt ob_start_closures.phpt /php-src/ext/xml/tests xml_closures_001.phpt
Modified files: /php-src/ext/mysqli mysqli_api.c /php-src/ext/standard basic_functions.c /php-src/ext/xml xml.c /php-src/main output.c Log: Support for closures
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli_api.c?r1=1.118.2.22.2.16.2.17&r2=1.118.2.22.2.16.2.18&diff_format=u Index: php-src/ext/mysqli/mysqli_api.c diff -u php-src/ext/mysqli/mysqli_api.c:1.118.2.22.2.16.2.17 php-src/ext/mysqli/mysqli_api.c:1.118.2.22.2.16.2.18 --- php-src/ext/mysqli/mysqli_api.c:1.118.2.22.2.16.2.17 Thu Apr 24 14:22:19 2008 +++ php-src/ext/mysqli/mysqli_api.c Thu Jul 17 09:53:41 2008 @@ -17,7 +17,7 @@ | Ulf Wendel <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: mysqli_api.c,v 1.118.2.22.2.16.2.17 2008/04/24 14:22:19 andrey Exp $ + $Id: mysqli_api.c,v 1.118.2.22.2.16.2.18 2008/07/17 09:53:41 dmitry Exp $ */ #ifdef HAVE_CONFIG_H @@ -1420,6 +1420,7 @@ efree(callback_name); RETURN_FALSE; } + efree(callback_name); /* save callback function */ if (!mysql->li_read) { @@ -1427,7 +1428,7 @@ } else { zval_dtor(mysql->li_read); } - ZVAL_STRING(mysql->li_read, callback_name, 0); + ZVAL_ZVAL(mysql->li_read, callback_func, 1, 0); RETURN_TRUE; } http://cvs.php.net/viewvc.cgi/php-src/ext/standard/basic_functions.c?r1=1.725.2.31.2.64.2.35&r2=1.725.2.31.2.64.2.36&diff_format=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.725.2.31.2.64.2.35 php-src/ext/standard/basic_functions.c:1.725.2.31.2.64.2.36 --- php-src/ext/standard/basic_functions.c:1.725.2.31.2.64.2.35 Sun May 25 14:06:13 2008 +++ php-src/ext/standard/basic_functions.c Thu Jul 17 09:53:42 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.725.2.31.2.64.2.35 2008/05/25 14:06:13 bjori Exp $ */ +/* $Id: basic_functions.c,v 1.725.2.31.2.64.2.36 2008/07/17 09:53:42 dmitry Exp $ */ #include "php.h" #include "php_streams.h" @@ -5392,6 +5392,10 @@ zval result; zend_compare_arrays(&result, func1, func2 TSRMLS_CC); ret = (Z_LVAL(result) == 0); + } else if (Z_TYPE_P(func1) == IS_OBJECT && Z_TYPE_P(func2) == IS_OBJECT) { + zval result; + zend_compare_objects(&result, func1, func2 TSRMLS_CC); + ret = (Z_LVAL(result) == 0); } else { ret = 0; } @@ -6044,7 +6048,7 @@ efree(function_name); } - if (Z_TYPE_P(tick_fe.arguments[0]) != IS_ARRAY) { + if (Z_TYPE_P(tick_fe.arguments[0]) != IS_ARRAY && Z_TYPE_P(tick_fe.arguments[0]) != IS_OBJECT) { convert_to_string_ex(&tick_fe.arguments[0]); } http://cvs.php.net/viewvc.cgi/php-src/ext/xml/xml.c?r1=1.157.2.4.2.5.2.8&r2=1.157.2.4.2.5.2.9&diff_format=u Index: php-src/ext/xml/xml.c diff -u php-src/ext/xml/xml.c:1.157.2.4.2.5.2.8 php-src/ext/xml/xml.c:1.157.2.4.2.5.2.9 --- php-src/ext/xml/xml.c:1.157.2.4.2.5.2.8 Sat Jul 5 20:17:58 2008 +++ php-src/ext/xml/xml.c Thu Jul 17 09:53:42 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: xml.c,v 1.157.2.4.2.5.2.8 2008/07/05 20:17:58 felipe Exp $ */ +/* $Id: xml.c,v 1.157.2.4.2.5.2.9 2008/07/17 09:53:42 dmitry Exp $ */ #define IS_EXT_MODULE @@ -508,7 +508,7 @@ } /* IS_ARRAY might indicate that we're using array($obj, 'method') syntax */ - if (Z_TYPE_PP(data) != IS_ARRAY) { + if (Z_TYPE_PP(data) != IS_ARRAY && Z_TYPE_PP(data) != IS_OBJECT) { convert_to_string_ex(data); if (Z_STRLEN_PP(data) == 0) { http://cvs.php.net/viewvc.cgi/php-src/main/output.c?r1=1.167.2.3.2.4.2.5&r2=1.167.2.3.2.4.2.6&diff_format=u Index: php-src/main/output.c diff -u php-src/main/output.c:1.167.2.3.2.4.2.5 php-src/main/output.c:1.167.2.3.2.4.2.6 --- php-src/main/output.c:1.167.2.3.2.4.2.5 Tue Jul 15 09:09:09 2008 +++ php-src/main/output.c Thu Jul 17 09:53:42 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: output.c,v 1.167.2.3.2.4.2.5 2008/07/15 09:09:09 lstrojny Exp $ */ +/* $Id: output.c,v 1.167.2.3.2.4.2.6 2008/07/17 09:53:42 dmitry Exp $ */ #include "php.h" #include "ext/standard/head.h" @@ -526,8 +526,17 @@ } } } else if (output_handler && output_handler->type == IS_OBJECT) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %s to use as output handler", Z_OBJCE_P(output_handler)->name); - result = FAILURE; + /* do we have callable object */ + if (zend_is_callable(output_handler, 0, &handler_name)) { + SEPARATE_ZVAL(&output_handler); + Z_ADDREF_P(output_handler); + result = php_ob_init_named(initial_size, block_size, handler_name, output_handler, chunk_size, erase TSRMLS_CC); + efree(handler_name); + } else { + efree(handler_name); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %s to use as output handler", Z_OBJCE_P(output_handler)->name); + result = FAILURE; + } } else { result = php_ob_init_named(initial_size, block_size, OB_DEFAULT_HANDLER_NAME, NULL, chunk_size, erase TSRMLS_CC); } http://cvs.php.net/viewvc.cgi/php-src/ext/curl/tests/curl_006.phpt?view=markup&rev=1.1 Index: php-src/ext/curl/tests/curl_006.phpt +++ php-src/ext/curl/tests/curl_006.phpt --TEST-- Test curl_opt() function with CURLOPT_WRITEFUNCTION paremter set to a closure --SKIPIF-- <?php if (!extension_loaded("curl") || false === getenv(b'PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?> --FILE-- <?php /* Prototype : bool curl_setopt(resource ch, int option, mixed value) * Description: Set an option for a cURL transfer * Source code: ext/curl/interface.c * Alias to functions: */ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER'); // start testing echo '*** Testing curl_setopt($ch, CURLOPT_WRITEFUNCTION, <closure>); ***' . "\n"; $url = "{$host}/get.php?test=get"; $ch = curl_init(); ob_start(); // start output buffering curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) { echo 'Data: '.$data; return strlen ($data); }); curl_exec($ch); curl_close($ch); ?> ===DONE=== --EXPECTF-- *** Testing curl_setopt($ch, CURLOPT_WRITEFUNCTION, <closure>); *** Data: Hello World! Hello World!===DONE=== http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/callback_closure.phpt?view=markup&rev=1.1 Index: php-src/ext/filter/tests/callback_closure.phpt +++ php-src/ext/filter/tests/callback_closure.phpt --TEST-- callback function is a closure --SKIPIF-- <?php if (!extension_loaded("filter")) die("skip"); ?> --FILE-- <?php $callback = function ($var) { return $var; }; $var = "test"; var_dump(filter_var($var, FILTER_CALLBACK, array('options'=> $callback))); ?> --EXPECT-- string(4) "test" http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt?view=markup&rev=1.1 Index: php-src/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt +++ php-src/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt --TEST-- mysqli_set_local_infile_handler() - use closures as handler --SKIPIF-- <?php require_once('skipif.inc'); require_once('skipifemb.inc'); require_once('skipifconnectfailure.inc'); if (!function_exists('mysqli_set_local_infile_handler')) die("skip - function not available."); require_once('connect.inc'); if (!$TEST_EXPERIMENTAL) die("skip - experimental (= unsupported) feature"); if (!$link = mysqli_connect($host, $user, $passwb, $db, $port, $socket)) die("skip Cannot connect to MySQL"); if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"')) { mysqli_close($link); die("skip Cannot check if Server variable 'local_infile' is set to 'ON'"); } $row = mysqli_fetch_assoc($res); mysqli_free_result($res); mysqli_close($link); if ('ON' != $row['Value']) die(sprintf("skip Server variable 'local_infile' seems not set to 'ON', found '%s'", $row['Value'])); ?> --INI-- mysqli.allow_local_infile=1 --FILE-- <?php require_once('connect.inc'); require_once('local_infile_tools.inc'); require_once('table.inc'); $callback_replace_buffer = function ($fp, &$buffer, $buflen, &$error) { static $invocation = 0; printf("Callback: %d\n", $invocation++); flush(); $buffer = fread($fp, $buflen); if ($invocation > 10) return 0; return strlen($buffer); }; $file = create_standard_csv(1); if (!try_handler(20, $link, $file, $callback_replace_buffer, null)) printf("[008] Failure\n"); mysqli_close($link); print "done!"; ?> --EXPECTF-- Callback set to 'Closure object' Callback: 0 Callback: 1 done! http://cvs.php.net/viewvc.cgi/php-src/ext/pcntl/tests/signal_closure_handler.phpt?view=markup&rev=1.1 Index: php-src/ext/pcntl/tests/signal_closure_handler.phpt +++ php-src/ext/pcntl/tests/signal_closure_handler.phpt --TEST-- Closures as a signal handler --SKIPIF-- <?php if (!extension_loaded("pcntl")) print "skip"; if (!function_exists("pcntl_signal")) print "skip pcntl_signal() not available"; if (!function_exists("posix_kill")) print "skip posix_kill() not available"; if (!function_exists("posix_getpid")) print "skip posix_getpid() not available"; ?> --FILE-- <?php declare (ticks = 1); pcntl_signal(SIGTERM, function ($signo) { echo "Signal handler called!\n"; }); echo "Start!\n"; posix_kill(posix_getpid(), SIGTERM); $i = 0; // dummy echo "Done!\n"; ?> --EXPECT-- Start! Signal handler called! Done! http://cvs.php.net/viewvc.cgi/php-src/ext/session/tests/save_handler_closures.inc?view=markup&rev=1.1 Index: php-src/ext/session/tests/save_handler_closures.inc +++ php-src/ext/session/tests/save_handler_closures.inc <?php require_once 'save_handler.inc'; foreach (array ('open', 'close', 'read', 'write', 'destroy', 'gc') as $fn) { ${$fn.'_closure'} = function () use ($fn) { return call_user_func_array ($fn, func_get_args ()); }; } ?> http://cvs.php.net/viewvc.cgi/php-src/ext/session/tests/session_set_save_handler_closures.phpt?view=markup&rev=1.1 Index: php-src/ext/session/tests/session_set_save_handler_closures.phpt +++ php-src/ext/session/tests/session_set_save_handler_closures.phpt --TEST-- Test session_set_save_handler() function : using closures as callbacks --INI-- session.save_path= session.name=PHPSESSID --SKIPIF-- <?php include('skipif.inc'); ?> --FILE-- <?php ob_start(); /* * Prototype : bool session_set_save_handler(callback $open, callback $close, callback $read, callback $write, callback $destroy, callback $gc) * Description : Sets user-level session storage functions * Source code : ext/session/session.c */ echo "*** Testing session_set_save_handler() : using closures as callbacks ***\n"; require_once "save_handler_closures.inc"; var_dump(session_module_name()); var_dump(session_module_name(FALSE)); var_dump(session_module_name("blah")); var_dump(session_module_name("foo")); $path = dirname(__FILE__); session_save_path($path); session_set_save_handler($open_closure, $close_closure, $read_closure, $write_closure, $destroy_closure, $gc_closure); session_start(); $_SESSION["Blah"] = "Hello World!"; $_SESSION["Foo"] = FALSE; $_SESSION["Guff"] = 1234567890; var_dump($_SESSION); session_write_close(); session_unset(); var_dump($_SESSION); echo "Starting session again..!\n"; session_id($session_id); session_set_save_handler($open_closure, $close_closure, $read_closure, $write_closure, $destroy_closure, $gc_closure); session_start(); var_dump($_SESSION); session_write_close(); ob_end_flush(); ?> --EXPECTF-- *** Testing session_set_save_handler() : using closures as callbacks *** unicode(%d) "%s" Warning: session_module_name(): Cannot find named PHP session module () in %s on line %d bool(false) Warning: session_module_name(): Cannot find named PHP session module (blah) in %s on line %d bool(false) Warning: session_module_name(): Cannot find named PHP session module (foo) in %s on line %d bool(false) Open [%s,PHPSESSID] Read [%s,%s] array(3) { [u"Blah"]=> unicode(12) "Hello World!" [u"Foo"]=> bool(false) [u"Guff"]=> int(1234567890) } Write [%s,%s,Blah|U:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] Notice: fwrite(): %d character unicode buffer downcoded for binary stream runtime_encoding in %s on line %d Close [%s,PHPSESSID] array(3) { [u"Blah"]=> unicode(12) "Hello World!" [u"Foo"]=> bool(false) [u"Guff"]=> int(1234567890) } Starting session again..! Open [%s,PHPSESSID] Read [%s,%s] array(3) { [u"Blah"]=> unicode(12) "Hello World!" [u"Foo"]=> bool(false) [u"Guff"]=> int(1234567890) } Write [%s,%s,Blah|U:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] Notice: fwrite(): %d character unicode buffer downcoded for binary stream runtime_encoding in %s on line %d Close [%s,PHPSESSID] http://cvs.php.net/viewvc.cgi/php-src/ext/sqlite/tests/sqlite_closures_001.phpt?view=markup&rev=1.1 Index: php-src/ext/sqlite/tests/sqlite_closures_001.phpt +++ php-src/ext/sqlite/tests/sqlite_closures_001.phpt --TEST-- sqlite: aggregate functions with closures --INI-- sqlite.assoc_case=0 --SKIPIF-- <?php # vim:ft=php if (!extension_loaded("sqlite")) print "skip"; ?> --FILE-- <?php include "blankdb.inc"; $data = array( "one", "two", "three" ); sqlite_query("CREATE TABLE strings(a)", $db); foreach ($data as $str) { sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db); } function cat_step(&$context, $string) { $context .= $string; } function cat_fin(&$context) { return $context; } sqlite_create_aggregate($db, "cat", function (&$context, $string) { $context .= $string; }, function (&$context) { return $context; }); $r = sqlite_query("SELECT cat(a) from strings", $db); while ($row = sqlite_fetch_array($r, SQLITE_NUM)) { var_dump($row); } sqlite_close($db); echo "DONE!\n"; ?> --EXPECT-- array(1) { [0]=> unicode(11) "onetwothree" } DONE! http://cvs.php.net/viewvc.cgi/php-src/ext/sqlite/tests/sqlite_closures_002.phpt?view=markup&rev=1.1 Index: php-src/ext/sqlite/tests/sqlite_closures_002.phpt +++ php-src/ext/sqlite/tests/sqlite_closures_002.phpt --TEST-- sqlite: regular functions with closures --INI-- sqlite.assoc_case=0 --SKIPIF-- <?php # vim:ft=php if (!extension_loaded("sqlite")) print "skip"; ?> --FILE-- <?php include "blankdb.inc"; $data = array( array("one", "uno"), array("two", "dos"), array("three", "tres"), ); sqlite_query("CREATE TABLE strings(a,b)", $db); foreach ($data as $row) { sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($row[0]) . "','" . sqlite_escape_string($row[1]) . "')", $db); } sqlite_create_function($db, "implode", function () { $args = func_get_args(); $sep = array_shift($args); return implode($sep, $args); }); $r = sqlite_query("SELECT implode('-', a, b) from strings", $db); while ($row = sqlite_fetch_array($r, SQLITE_NUM)) { var_dump($row); } sqlite_close($db); echo "DONE!\n"; ?> --EXPECT-- array(1) { [0]=> unicode(7) "one-uno" } array(1) { [0]=> unicode(7) "two-dos" } array(1) { [0]=> unicode(10) "three-tres" } DONE! http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/assert/assert_closures.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/assert/assert_closures.phpt +++ php-src/ext/standard/tests/assert/assert_closures.phpt --TEST-- assert() - basic - accept closures as callback. --INI-- assert.active = 1 assert.warning = 1 assert.bail = 0 assert.quiet_eval = 0 --FILE-- <?php assert_options(ASSERT_CALLBACK, function () { echo "Hello World!\n"; }); assert(0); ?> --EXPECTF-- Hello World! Warning: assert(): Assertion failed in %s on line %d http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/general_functions/closures_001.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/general_functions/closures_001.phpt +++ php-src/ext/standard/tests/general_functions/closures_001.phpt --TEST-- register_shutdown_function() & closure --FILE-- <?php register_shutdown_function(function () { echo "Hello World!\n"; }); echo "Done\n"; ?> --EXPECTF-- Done Hello World! http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/general_functions/closures_002.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/general_functions/closures_002.phpt +++ php-src/ext/standard/tests/general_functions/closures_002.phpt --TEST-- register_tick_function() & closure --FILE-- <?php declare (ticks = 1); $i = 0; register_tick_function(function () use (&$i) { $i++; }); echo "Test\n"; echo "$i\n"; echo "$i\n"; var_dump ($i != 0); echo "$i\n"; echo "Done\n"; ?> --EXPECTF-- Test %d %d bool(true) %d Done http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/general_functions/ob_start_closures.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/general_functions/ob_start_closures.phpt +++ php-src/ext/standard/tests/general_functions/ob_start_closures.phpt --TEST-- Test ob_start() function : closures as output handlers --INI-- output_buffering=0 --FILE-- <?php echo "*** Testing ob_start() : closures as output handlers ***\n"; ob_start(function ($output) { return 'Output (1): ' . $output; }); ob_start(function ($output) { return 'Output (2): ' . $output; }); echo "Test\nWith newlines\n"; $str1 = ob_get_contents (); ob_end_flush(); $str2 = ob_get_contents (); ob_end_flush(); echo $str1, $str2; ?> ===DONE=== --EXPECT-- *** Testing ob_start() : closures as output handlers *** Output (1): Output (2): Test With newlines Test With newlines Output (2): Test With newlines ===DONE=== http://cvs.php.net/viewvc.cgi/php-src/ext/xml/tests/xml_closures_001.phpt?view=markup&rev=1.1 Index: php-src/ext/xml/tests/xml_closures_001.phpt +++ php-src/ext/xml/tests/xml_closures_001.phpt --TEST-- XML parser test using closures as callbacks --SKIPIF-- <?php include("skipif.inc"); ?> --INI-- magic_quotes_runtime=0 --FILE-- <?php chdir(dirname(__FILE__)); $start_element = function ($xp, $elem, $attribs) { print "<$elem"; if (sizeof($attribs)) { while (list($k, $v) = each($attribs)) { print " $k=\"$v\""; } } print ">\n"; }; $end_element = function ($xp, $elem) { print "</$elem>\n"; }; $xp = xml_parser_create(); xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); xml_set_element_handler($xp, $start_element, $end_element); $fp = fopen("xmltest.xml", "r"); while ($data = fread($fp, 4096)) { xml_parse($xp, $data, feof($fp)); } xml_parser_free($xp); ?> --EXPECT-- <root id="elem1"> <elem1> <elem2> <elem3> <elem4> </elem4> </elem3> </elem2> </elem1> </root>
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php