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