--- /dev/null
+--TEST--
+declare bare anonymous class
+--FILE--
+<?php
+var_dump(new class{});
+--EXPECTF--
+object(class@%s)#%d (0) {
+}
+
+
--- /dev/null
+--TEST--
+declare anonymous class extending another
+--FILE--
+<?php
+class A{}
+
+interface B{
+ public function method();
+}
+
+$a = new class extends A implements B {
+ public function method(){
+ return true;
+ }
+};
+
+var_dump($a instanceof A, $a instanceof B);
+--EXPECTF--
+bool(true)
+bool(true)
+
--- /dev/null
+--TEST--
+reusing anonymous classes
+--FILE--
+<?php
+while (@$i++<10) {
+ var_dump(new class($i) {
+
+ public function __construct($i) {
+ $this->i = $i;
+ }
+ });
+}
+--EXPECTF--
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(1)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(2)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(3)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(4)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(5)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(6)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(7)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(8)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(9)
+}
+object(class@%s)#1 (1) {
+ ["i"]=>
+ int(10)
+}
+
--- /dev/null
+--TEST--
+testing anonymous inheritance
+--FILE--
+<?php
+class Outer {
+ protected $data;
+
+ public function __construct($data) {
+ $this->data = $data;
+ }
+
+ public function getArrayAccess() {
+ /* create a proxy object implementing array access */
+ return new class($this->data) extends Outer implements ArrayAccess {
+ public function offsetGet($offset) { return $this->data[$offset]; }
+ public function offsetSet($offset, $data) { return ($this->data[$offset] = $data); }
+ public function offsetUnset($offset) { unset($this->data[$offset]); }
+ public function offsetExists($offset) { return isset($this->data[$offset]); }
+ };
+ }
+}
+
+$outer = new Outer(array(
+ rand(1, 100)
+));
+
+/* not null because inheritance */
+var_dump($outer->getArrayAccess()[0]);
+--EXPECTF--
+int(%d)
--- /dev/null
+--TEST--
+testing reusing anons that implement an interface
+--FILE--
+<?php
+class Outer {
+ protected $data;
+
+ public function __construct(&$data) {
+ /* array access will be implemented by the time we get to here */
+ $this->data = &$data;
+ }
+
+ public function getArrayAccess() {
+ /* create a child object implementing array access */
+ /* this grants you access to protected methods and members */
+ return new class($this->data) implements ArrayAccess {
+ public function offsetGet($offset) { return $this->data[$offset]; }
+ public function offsetSet($offset, $data) { return ($this->data[$offset] = $data); }
+ public function offsetUnset($offset) { unset($this->data[$offset]); }
+ public function offsetExists($offset) { return isset($this->data[$offset]); }
+ };
+ }
+}
+
+$data = array(
+ rand(1, 100),
+ rand(2, 200)
+);
+
+$outer = new Outer($data);
+$proxy = $outer->getArrayAccess();
+
+/* null because no inheritance, so no access to protected member */
+var_dump(@$outer->getArrayAccess()[0]);
+--EXPECT--
+NULL
--- /dev/null
+--TEST--
+testing anon classes inside namespaces
+--FILE--
+<?php
+namespace lone {
+ $hello = new class{} ;
+}
+
+namespace {
+ var_dump ($hello);
+}
+--EXPECTF--
+object(lone\class@%s)#1 (0) {
+}
+
--- /dev/null
+--TEST--
+testing anon classes in functions outside of classes in namespaces
+--FILE--
+<?php
+namespace lone {
+ function my_factory() {
+ return new class{};
+ }
+
+ class Outer {
+
+ public function __construct() {
+ var_dump(
+ my_factory());
+ }
+ }
+
+ new Outer();
+}
+--EXPECTF--
+object(lone\class@%s)#2 (0) {
+}
+
--- /dev/null
+--TEST--
+testing static access for methods and properties in anon classes
+--FILE--
+<?php
+$anonClass = new class("cats", "dogs") {
+ public static $foo;
+ private static $bar;
+
+ public function __construct($foo, $bar) {
+ static::$foo = $foo;
+ static::$bar = $bar;
+ }
+
+ public static function getBar() {
+ return static::$bar;
+ }
+};
+
+var_dump($anonClass::$foo);
+var_dump($anonClass::getBar());
+--EXPECT--
+string(4) "cats"
+string(4) "dogs"
--- /dev/null
+--TEST--
+testing traits in anon classes
+--FILE--
+<?php
+
+trait Foo {
+ public function someMethod() {
+ return "bar";
+ }
+}
+
+$anonClass = new class {
+ use Foo;
+};
+
+var_dump($anonClass->someMethod());
+--EXPECT--
+string(3) "bar"
case ZEND_AST_CLASS:
{
zend_ast_decl *decl = (zend_ast_decl *) ast;
- zend_string_release(decl->name);
+ if (decl->name) {
+ zend_string_release(decl->name);
+ }
if (decl->doc_comment) {
zend_string_release(decl->doc_comment);
}
ZEND_ARG_INFO(0, code)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0)
+ ZEND_ARG_INFO(0, disabled)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
ZEND_ARG_INFO(0, res)
ZEND_END_ARG_INFO()
ZEND_FE(get_declared_classes, arginfo_zend__void)
ZEND_FE(get_declared_traits, arginfo_zend__void)
ZEND_FE(get_declared_interfaces, arginfo_zend__void)
- ZEND_FE(get_defined_functions, arginfo_zend__void)
+ ZEND_FE(get_defined_functions, arginfo_get_defined_functions)
ZEND_FE(get_defined_vars, arginfo_zend__void)
ZEND_FE(create_function, arginfo_create_function)
ZEND_FE(get_resource_type, arginfo_get_resource_type)
static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
zend_function *func = Z_PTR_P(zv);
- zval *internal_ar = va_arg(args, zval *),
- *user_ar = va_arg(args, zval *);
+ zval *internal_ar = va_arg(args, zval *),
+ *user_ar = va_arg(args, zval *);
+ zend_bool *disabled = va_arg(args, zend_bool*);
if (hash_key->key == NULL || hash_key->key->val[0] == 0) {
return 0;
}
if (func->type == ZEND_INTERNAL_FUNCTION) {
- add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
+ zend_internal_function *intern = (zend_internal_function*) func;
+ if ((*disabled) || intern->handler != ZEND_FN(display_disabled_function)) {
+ add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
+ }
} else if (func->type == ZEND_USER_FUNCTION) {
add_next_index_str(user_ar, zend_string_copy(hash_key->key));
}
}
/* }}} */
-/* {{{ proto array get_defined_functions(void)
+/* {{{ proto array get_defined_functions(bool disabled = false)
Returns an array of all defined functions */
ZEND_FUNCTION(get_defined_functions)
{
zval internal, user;
+ zend_bool disabled = 0;
- if (zend_parse_parameters_none() == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &disabled) == FAILURE) {
return;
}
array_init(&user);
array_init(return_value);
- zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 2, &internal, &user);
+ zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 3, &internal, &user, &disabled);
zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user);
#include "zend_llist.h"
#include "zend_API.h"
#include "zend_exceptions.h"
+#include "zend_interfaces.h"
#include "zend_virtual_cwd.h"
#include "zend_multibyte.h"
#include "zend_language_scanner.h"
zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
return NULL;
}
+
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ return ce;
+ }
+
ce->refcount++;
+
if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
ce->refcount--;
+
if (!compile_time) {
/* If we're in compile time, in practice, it's quite possible
* that we'll never reach this class declaration at runtime,
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ce->name->val);
}
- zend_do_inheritance(ce, parent_ce);
+ /* Reuse anonymous bound class */
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ return ce;
+ }
+
+ zend_do_inheritance(ce, parent_ce TSRMLS_CC);
ce->refcount++;
if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ce->name->val);
}
+
return ce;
}
/* }}} */
}
/* }}} */
-void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
+zend_string* zend_name_anon_class(zend_ast *parent TSRMLS_DC) {
+ size_t len;
+ char *val;
+ zend_string *anon;
+ uint32_t next = get_next_op_number(CG(active_op_array));
+
+ if (parent) {
+ zval *extends = zend_ast_get_zval(parent);
+ len = zend_spprintf(
+ &val, 0, "%s@%p",
+ Z_STRVAL_P(extends), &CG(active_op_array)->opcodes[next-1]);
+ anon = zend_string_init(val, len, 1);
+ Z_DELREF_P(extends); /* ?? */
+ efree(val);
+ } else {
+ len = zend_spprintf(
+ &val, 0, "class@%p",
+ &CG(active_op_array)->opcodes[next-1]);
+ anon = zend_string_init(val, len, 1);
+ efree(val);
+ }
+
+ return anon;
+} /* }}} */
+
+zend_class_entry *zend_compile_class_decl(zend_ast *ast);
+
+void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
zend_ast *class_ast = ast->child[0];
zend_ast *args_ast = ast->child[1];
class_node.op_type = IS_CONST;
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
} else {
- zend_compile_class_ref(&class_node, class_ast, 1);
+ if (class_ast->kind == ZEND_AST_CLASS) {
+ zend_class_entry *ce =
+ zend_compile_class_decl(class_ast TSRMLS_CC);
+ zend_string *name = ce->name;
+ uint32_t fetch_type = zend_get_class_fetch_type(name);
+
+ opline = zend_emit_op(&class_node,
+ ZEND_FETCH_CLASS, NULL, NULL TSRMLS_CC);
+ opline->extended_value = fetch_type;
+
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name(name, ZEND_NAME_FQ TSRMLS_CC) TSRMLS_CC);
+ }
+
+ zend_string_release(name);
+ } else {
+ zend_compile_class_ref(&class_node, class_ast, 1);
+ }
}
opnum = get_next_op_number(CG(active_op_array));
}
/* }}} */
-void zend_compile_class_decl(zend_ast *ast) /* {{{ */
+zend_class_entry *zend_compile_class_decl(zend_ast *ast) /* {{{ */
{
zend_ast_decl *decl = (zend_ast_decl *) ast;
zend_ast *extends_ast = decl->child[0];
zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
zend_op *opline;
znode declare_node, extends_node;
+ zend_class_entry *active = CG(active_class_entry);
+
+ if (decl->flags & ZEND_ACC_ANON_CLASS) {
+ name =
+ zend_name_anon_class((zend_ast*)name TSRMLS_CC);
- if (CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
- return;
+ /* do not support serial classes */
+ ce->serialize = zend_class_serialize_deny;
+ ce->unserialize = zend_class_unserialize_deny;
}
+
+ if (CG(active_class_entry) && !((decl->flags & ZEND_ACC_ANON_CLASS) == ZEND_ACC_ANON_CLASS)) {
+ zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
+ return NULL;
+ }
zend_assert_valid_class_name(name);
name = zend_prefix_with_ns(name);
zend_string_release(lcname);
- lcname = zend_string_tolower(name);
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
} else {
zend_string_addref(name);
}
"because the name is already in use", name->val);
}
- name = zend_new_interned_string(name);
- lcname = zend_new_interned_string(lcname);
+ name = zend_new_interned_string(name TSRMLS_CC);
+ lcname = zend_new_interned_string(lcname TSRMLS_CC);
ce->type = ZEND_USER_CLASS;
ce->name = name;
- zend_initialize_class_data(ce, 1);
+ zend_initialize_class_data(ce, 1 TSRMLS_CC);
ce->ce_flags |= decl->flags;
- ce->info.user.filename = zend_get_compiled_filename();
+ ce->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
ce->info.user.line_start = decl->start_lineno;
ce->info.user.line_end = decl->end_lineno;
if (decl->doc_comment) {
}
if (extends_ast) {
+ if (ce->ce_flags & ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. "
+ "Traits can only be composed from other traits with the 'use' keyword. Error",
+ name->val);
+ }
+
if (!zend_is_const_default_class_ref(extends_ast)) {
zend_string *extends_name = zend_ast_get_str(extends_ast);
zend_error_noreturn(E_COMPILE_ERROR,
zend_compile_class_ref(&extends_node, extends_ast, 0);
}
- opline = get_next_op(CG(active_op_array));
- zend_make_var_result(&declare_node, opline);
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_make_var_result(&declare_node, opline TSRMLS_CC);
// TODO.AST drop this
GET_NODE(&FC(implementing_class), opline->result);
}
{
- zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
+ zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos TSRMLS_CC);
opline->op1_type = IS_CONST;
LITERAL_STR(opline->op1, key);
CG(active_class_entry) = ce;
if (implements_ast) {
- zend_compile_implements(&declare_node, implements_ast);
+ zend_compile_implements(&declare_node, implements_ast TSRMLS_CC);
}
- zend_compile_stmt(stmt_ast);
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
if (ce->num_traits == 0) {
/* For traits this check is delayed until after trait binding */
zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
ce->name->val, ce->constructor->common.function_name->val);
}
- if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Constructor %s::%s() cannot declare a return type",
- ce->name->val, ce->constructor->common.function_name->val);
- }
}
if (ce->destructor) {
ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
ce->name->val, ce->destructor->common.function_name->val);
- } else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Destructor %s::%s() cannot declare a return type",
- ce->name->val, ce->destructor->common.function_name->val);
}
}
if (ce->clone) {
if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static",
ce->name->val, ce->clone->common.function_name->val);
- } else if (ce->clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "%s::%s() cannot declare a return type",
- ce->name->val, ce->clone->common.function_name->val);
}
}
ce->num_traits = 0;
ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
- zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL);
+ zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL TSRMLS_CC);
}
if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
&& (extends_ast || ce->num_interfaces > 0)
) {
- zend_verify_abstract_class(ce);
+ zend_verify_abstract_class(ce TSRMLS_CC);
if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
- zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL);
+ zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL TSRMLS_CC);
}
}
ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
}
- CG(active_class_entry) = NULL;
+ CG(active_class_entry) = active;
+
+ return ce;
}
/* }}} */
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20
#define ZEND_ACC_INTERFACE 0x40
#define ZEND_ACC_TRAIT 0x80
+#define ZEND_ACC_ANON_CLASS 0x100
+#define ZEND_ACC_ANON_BOUND 0x200
/* method flags (visibility) */
/* The order of those must be kept - public < protected < private */
%type <ast> extends_from parameter optional_type argument expr_without_variable global_var
%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias
%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr
-%type <ast> new_expr class_name class_name_reference simple_variable internal_functions_in_yacc
+%type <ast> new_expr anonymous_class class_name class_name_reference simple_variable internal_functions_in_yacc
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name
%type <ast> variable_class_name dereferencable_scalar class_name_scalar constant dereferencable
%type <ast> callable_expr callable_variable static_member new_variable
| expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); }
;
+anonymous_class:
+ T_CLASS ctor_arguments {
+ $<num>$ = CG(zend_lineno);
+ } extends_from implements_list backup_doc_comment '{' class_statement_list '}' {
+ zend_ast *decl = zend_ast_create_decl(
+ ZEND_AST_CLASS,
+ ZEND_ACC_ANON_CLASS,
+ $<num>3, $6, $4, $4, $5, $8, NULL);
+ $$ = zend_ast_create(ZEND_AST_NEW, decl, $2);
+ }
+;
+
new_expr:
T_NEW class_name_reference ctor_arguments
{ $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); }
+ | T_NEW anonymous_class
+ { $$ = $2; }
;
expr_without_variable:
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
+ while (opline->opcode != ZEND_FETCH_CLASS) {
+ opline++;
+ }
+ ZEND_VM_JMP(opline);
+ } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
+ while (opline->opcode != ZEND_FETCH_CLASS) {
+ opline++;
+ }
+ ZEND_VM_JMP(opline);
+ } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
+ while (opline->opcode != ZEND_FETCH_CLASS) {
+ opline++;
+ }
+ ZEND_VM_JMP(opline);
+ } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
+ if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
+ while (opline->opcode != ZEND_FETCH_CLASS) {
+ opline++;
+ }
+ ZEND_VM_JMP(opline);
+ } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
/* }}} */
+/* {{{ proto public bool ReflectionClass::isAnonymous()
+ Returns whether this class is anonymous */
+ZEND_METHOD(reflection_class, isAnonymous)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+ RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
+}
+/* }}} */
+
/* {{{ proto public string ReflectionClass::getFileName()
Returns the filename of the file this class was declared in */
ZEND_METHOD(reflection_class, getFileName)
ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, isAnonymous, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
--- /dev/null
+--TEST--
+ReflectionClass::isAnonymous() method
+--FILE--
+<?php
+
+class TestClass {}
+
+$declaredClass = new ReflectionClass('TestClass');
+$anonymousClass = new ReflectionClass(new class {});
+
+var_dump($declaredClass->isAnonymous());
+var_dump($anonymousClass->isAnonymous());
+
+?>
+--EXPECT--
+bool(false)
+bool(true)
Property [ <default> public $name ]
}
- - Methods [49] {
+ - Methods [50] {
Method [ <internal:Reflection> final private method __clone ] {
- Parameters [0] {
}
}
+ Method [ <internal:Reflection> public method isAnonymous ] {
+
+ - Parameters [0] {
+ }
+ }
+
Method [ <internal:Reflection> public method isInstantiable ] {
- Parameters [0] {