--- /dev/null
+--TEST--
+Closure 016: closures and is_callable()
+--FILE--
+<?php
+class Foo {
+ function __invoke() {
+ echo "Hello World!\n";
+ }
+}
+
+function foo() {
+ return function() {
+ echo "Hello World!\n";
+ };
+}
+$test = new Foo;
+var_dump(is_callable($test, true, $name));
+echo $name."\n";
+var_dump(is_callable($test, false, $name));
+echo $name."\n";
+var_dump(is_callable(array($test,"__invoke"), true, $name));
+echo $name."\n";
+var_dump(is_callable(array($test,"__invoke"), false, $name));
+echo $name."\n";
+$test = foo();
+var_dump(is_callable($test, true, $name));
+echo $name."\n";
+var_dump(is_callable($test, false, $name));
+echo $name."\n";
+var_dump(is_callable(array($test,"__invoke"), true, $name));
+echo $name."\n";
+var_dump(is_callable(array($test,"__invoke"), false, $name));
+echo $name."\n";
+?>
+--EXPECT--
+bool(true)
+Foo::__invoke
+bool(true)
+Foo::__invoke
+bool(true)
+Foo::__invoke
+bool(true)
+Foo::__invoke
+bool(true)
+Closure::__invoke
+bool(true)
+Closure::__invoke
+bool(true)
+Closure::__invoke
+bool(true)
+Closure::__invoke
case IS_OBJECT:
if (zend_get_closure(callable, ce_ptr, fptr_ptr, NULL, zobj_ptr_ptr TSRMLS_CC) == SUCCESS) {
if (callable_name) {
- ZVAL_ZSTR(callable_name, UG(unicode) ? IS_UNICODE : IS_STRING, (*fptr_ptr)->common.function_name, 1);
+ zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
+
+ if (UG(unicode)) {
+ Z_TYPE_P(callable_name) = IS_UNICODE;
+ Z_USTRLEN_P(callable_name) = ce->name_length + sizeof("::__invoke") - 1;
+ Z_USTRVAL_P(callable_name) = eumalloc(Z_USTRLEN_P(callable_name)+1);
+ u_memcpy(Z_USTRVAL_P(callable_name), ce->name.u, ce->name_length);
+ u_charsToUChars("::__invoke", Z_USTRVAL_P(callable_name) + ce->name_length, sizeof("::__invoke"));
+ } else {
+ Z_TYPE_P(callable_name) = IS_STRING;
+ Z_STRLEN_P(callable_name) = ce->name_length + sizeof("::__invoke") - 1;
+ Z_STRVAL_P(callable_name) = emalloc(Z_STRLEN_P(callable_name) + 1);
+ memcpy(Z_STRVAL_P(callable_name), ce->name.s, ce->name_length);
+ memcpy(Z_STRVAL_P(callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke"));
+ }
}
return 1;
}
}
/* }}} */
+const static zend_function_entry closure_functions[] = { /* {{{ */
+ ZEND_ME(Closure, __invoke, NULL, 0)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{{ */
{
zend_error(E_ERROR, "Instantiation of 'Closure' is not allowed");
{
zend_class_entry ce;
- INIT_CLASS_ENTRY(ce, "Closure", NULL);
+ INIT_CLASS_ENTRY(ce, "Closure", closure_functions);
zend_ce_closure = zend_register_internal_class(&ce TSRMLS_CC);
zend_ce_closure->ce_flags |= ZEND_ACC_FINAL_CLASS;
zend_ce_closure->create_object = zend_closure_new;
zend_op *current_op;
function_name.op_type = IS_CONST;
- ZVAL_ASCII_STRING(&function_name.u.constant, "lambda", ZSTR_DUPLICATE);
+ ZVAL_ASCII_STRING(&function_name.u.constant, "", ZSTR_DUPLICATE);
zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);