1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Timm Friebe <thekid@thekid.de> |
16 | George Schlossnagle <george@omniti.com> |
17 | Andrei Zmievski <andrei@gravitonic.com> |
18 | Marcus Boerger <helly@php.net> |
19 | Johannes Schlueter <johannes@php.net> |
20 +----------------------------------------------------------------------+
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_reflection.h"
30 #include "ext/standard/info.h"
31
32 #include "zend.h"
33 #include "zend_API.h"
34 #include "zend_exceptions.h"
35 #include "zend_operators.h"
36 #include "zend_constants.h"
37 #include "zend_ini.h"
38 #include "zend_interfaces.h"
39 #include "zend_closures.h"
40 #include "zend_generators.h"
41 #include "zend_extensions.h"
42 #include "zend_builtin_functions.h"
43 #include "zend_smart_str.h"
44
45 #define reflection_update_property(object, name, value) do { \
46 zval member; \
47 ZVAL_STR(&member, name); \
48 zend_std_write_property(object, &member, value, NULL); \
49 Z_TRY_DELREF_P(value); \
50 zval_ptr_dtor(&member); \
51 } while (0)
52
53 #define reflection_update_property_name(object, value) \
54 reflection_update_property(object, ZSTR_KNOWN(ZEND_STR_NAME), value)
55
56 #define reflection_update_property_class(object, value) \
57 reflection_update_property(object, ZSTR_KNOWN(ZEND_STR_CLASS), value)
58
59 /* Class entry pointers */
60 PHPAPI zend_class_entry *reflector_ptr;
61 PHPAPI zend_class_entry *reflection_exception_ptr;
62 PHPAPI zend_class_entry *reflection_ptr;
63 PHPAPI zend_class_entry *reflection_function_abstract_ptr;
64 PHPAPI zend_class_entry *reflection_function_ptr;
65 PHPAPI zend_class_entry *reflection_generator_ptr;
66 PHPAPI zend_class_entry *reflection_parameter_ptr;
67 PHPAPI zend_class_entry *reflection_type_ptr;
68 PHPAPI zend_class_entry *reflection_named_type_ptr;
69 PHPAPI zend_class_entry *reflection_class_ptr;
70 PHPAPI zend_class_entry *reflection_object_ptr;
71 PHPAPI zend_class_entry *reflection_method_ptr;
72 PHPAPI zend_class_entry *reflection_property_ptr;
73 PHPAPI zend_class_entry *reflection_class_constant_ptr;
74 PHPAPI zend_class_entry *reflection_extension_ptr;
75 PHPAPI zend_class_entry *reflection_zend_extension_ptr;
76
77 /* Exception throwing macro */
78 #define _DO_THROW(msg) \
79 zend_throw_exception(reflection_exception_ptr, msg, 0); \
80 return; \
81
82 #define RETURN_ON_EXCEPTION \
83 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) { \
84 return; \
85 }
86
87 #define GET_REFLECTION_OBJECT() \
88 intern = Z_REFLECTION_P(getThis()); \
89 if (intern->ptr == NULL) { \
90 RETURN_ON_EXCEPTION \
91 zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
92 return; \
93 } \
94
95 #define GET_REFLECTION_OBJECT_PTR(target) \
96 GET_REFLECTION_OBJECT() \
97 target = intern->ptr; \
98
99 /* Class constants */
100 #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value) \
101 zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
102
103 /* {{{ Object structure */
104
105 /* Struct for properties */
106 typedef struct _property_reference {
107 zend_class_entry *ce;
108 zend_property_info prop;
109 zend_string *unmangled_name;
110 } property_reference;
111
112 /* Struct for parameters */
113 typedef struct _parameter_reference {
114 uint32_t offset;
115 zend_bool required;
116 struct _zend_arg_info *arg_info;
117 zend_function *fptr;
118 } parameter_reference;
119
120 /* Struct for type hints */
121 typedef struct _type_reference {
122 struct _zend_arg_info *arg_info;
123 zend_function *fptr;
124 } type_reference;
125
126 typedef enum {
127 REF_TYPE_OTHER, /* Must be 0 */
128 REF_TYPE_FUNCTION,
129 REF_TYPE_GENERATOR,
130 REF_TYPE_PARAMETER,
131 REF_TYPE_TYPE,
132 REF_TYPE_PROPERTY,
133 REF_TYPE_CLASS_CONSTANT
134 } reflection_type_t;
135
136 /* Struct for reflection objects */
137 typedef struct {
138 zval dummy; /* holder for the second property */
139 zval obj;
140 void *ptr;
141 zend_class_entry *ce;
142 reflection_type_t ref_type;
143 unsigned int ignore_visibility:1;
144 zend_object zo;
145 } reflection_object;
146
reflection_object_from_obj(zend_object * obj)147 static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
148 return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
149 }
150
151 #define Z_REFLECTION_P(zv) reflection_object_from_obj(Z_OBJ_P((zv)))
152 /* }}} */
153
154 static zend_object_handlers reflection_object_handlers;
155
_default_load_name(zval * object)156 static zval *_default_load_name(zval *object) /* {{{ */
157 {
158 return zend_hash_find_ex_ind(Z_OBJPROP_P(object), ZSTR_KNOWN(ZEND_STR_NAME), 1);
159 }
160 /* }}} */
161
_default_get_name(zval * object,zval * return_value)162 static void _default_get_name(zval *object, zval *return_value) /* {{{ */
163 {
164 zval *value;
165
166 if ((value = _default_load_name(object)) == NULL) {
167 RETURN_FALSE;
168 }
169 ZVAL_COPY(return_value, value);
170 }
171 /* }}} */
172
_copy_function(zend_function * fptr)173 static zend_function *_copy_function(zend_function *fptr) /* {{{ */
174 {
175 if (fptr
176 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
177 {
178 zend_function *copy_fptr;
179 copy_fptr = emalloc(sizeof(zend_function));
180 memcpy(copy_fptr, fptr, sizeof(zend_function));
181 copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
182 return copy_fptr;
183 } else {
184 /* no copy needed */
185 return fptr;
186 }
187 }
188 /* }}} */
189
_free_function(zend_function * fptr)190 static void _free_function(zend_function *fptr) /* {{{ */
191 {
192 if (fptr
193 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
194 {
195 zend_string_release_ex(fptr->internal_function.function_name, 0);
196 zend_free_trampoline(fptr);
197 }
198 }
199 /* }}} */
200
reflection_free_objects_storage(zend_object * object)201 static void reflection_free_objects_storage(zend_object *object) /* {{{ */
202 {
203 reflection_object *intern = reflection_object_from_obj(object);
204 parameter_reference *reference;
205 property_reference *prop_reference;
206 type_reference *typ_reference;
207
208 if (intern->ptr) {
209 switch (intern->ref_type) {
210 case REF_TYPE_PARAMETER:
211 reference = (parameter_reference*)intern->ptr;
212 _free_function(reference->fptr);
213 efree(intern->ptr);
214 break;
215 case REF_TYPE_TYPE:
216 typ_reference = (type_reference*)intern->ptr;
217 _free_function(typ_reference->fptr);
218 efree(intern->ptr);
219 break;
220 case REF_TYPE_FUNCTION:
221 _free_function(intern->ptr);
222 break;
223 case REF_TYPE_PROPERTY:
224 prop_reference = (property_reference*)intern->ptr;
225 zend_string_release_ex(prop_reference->unmangled_name, 0);
226 efree(intern->ptr);
227 break;
228 case REF_TYPE_GENERATOR:
229 case REF_TYPE_CLASS_CONSTANT:
230 case REF_TYPE_OTHER:
231 break;
232 }
233 }
234 intern->ptr = NULL;
235 zval_ptr_dtor(&intern->obj);
236 zend_object_std_dtor(object);
237 }
238 /* }}} */
239
reflection_get_gc(zval * obj,zval ** gc_data,int * gc_data_count)240 static HashTable *reflection_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */
241 {
242 reflection_object *intern = Z_REFLECTION_P(obj);
243 *gc_data = &intern->obj;
244 *gc_data_count = 1;
245 return zend_std_get_properties(obj);
246 }
247 /* }}} */
248
reflection_objects_new(zend_class_entry * class_type)249 static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
250 {
251 reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
252
253 zend_object_std_init(&intern->zo, class_type);
254 object_properties_init(&intern->zo, class_type);
255 intern->zo.handlers = &reflection_object_handlers;
256 return &intern->zo;
257 }
258 /* }}} */
259
reflection_instantiate(zend_class_entry * pce,zval * object)260 static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
261 {
262 object_init_ex(object, pce);
263 return object;
264 }
265 /* }}} */
266
267 static void _const_string(smart_str *str, char *name, zval *value, char *indent);
268 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
269 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent);
270 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
271 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
272 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
273 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent);
274
275 /* {{{ _class_string */
_class_string(smart_str * str,zend_class_entry * ce,zval * obj,char * indent)276 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent)
277 {
278 int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
279 zend_string *sub_indent = strpprintf(0, "%s ", indent);
280
281 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
282 if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
283 smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
284 smart_str_appendc(str, '\n');
285 }
286
287 if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
288 smart_str_append_printf(str, "%sObject of class [ ", indent);
289 } else {
290 char *kind = "Class";
291 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
292 kind = "Interface";
293 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
294 kind = "Trait";
295 }
296 smart_str_append_printf(str, "%s%s [ ", indent, kind);
297 }
298 smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
299 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
300 smart_str_append_printf(str, ":%s", ce->info.internal.module->name);
301 }
302 smart_str_append_printf(str, "> ");
303 if (ce->get_iterator != NULL) {
304 smart_str_append_printf(str, "<iterateable> ");
305 }
306 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
307 smart_str_append_printf(str, "interface ");
308 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
309 smart_str_append_printf(str, "trait ");
310 } else {
311 if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
312 smart_str_append_printf(str, "abstract ");
313 }
314 if (ce->ce_flags & ZEND_ACC_FINAL) {
315 smart_str_append_printf(str, "final ");
316 }
317 smart_str_append_printf(str, "class ");
318 }
319 smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
320 if (ce->parent) {
321 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
322 }
323
324 if (ce->num_interfaces) {
325 uint32_t i;
326
327 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
328 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
329 } else {
330 smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
331 }
332 for (i = 1; i < ce->num_interfaces; ++i) {
333 smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
334 }
335 }
336 smart_str_append_printf(str, " ] {\n");
337
338 /* The information where a class is declared is only available for user classes */
339 if (ce->type == ZEND_USER_CLASS) {
340 smart_str_append_printf(str, "%s @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
341 ce->info.user.line_start, ce->info.user.line_end);
342 }
343
344 /* Constants */
345 smart_str_append_printf(str, "\n");
346 count = zend_hash_num_elements(&ce->constants_table);
347 smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count);
348 if (count > 0) {
349 zend_string *key;
350 zend_class_constant *c;
351
352 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
353 _class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
354 if (UNEXPECTED(EG(exception))) {
355 return;
356 }
357 } ZEND_HASH_FOREACH_END();
358 }
359 smart_str_append_printf(str, "%s }\n", indent);
360
361 /* Static properties */
362 /* counting static properties */
363 count = zend_hash_num_elements(&ce->properties_info);
364 if (count > 0) {
365 zend_property_info *prop;
366
367 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
368 if(prop->flags & ZEND_ACC_SHADOW) {
369 count_shadow_props++;
370 } else if (prop->flags & ZEND_ACC_STATIC) {
371 count_static_props++;
372 }
373 } ZEND_HASH_FOREACH_END();
374 }
375
376 /* static properties */
377 smart_str_append_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
378 if (count_static_props > 0) {
379 zend_property_info *prop;
380
381 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
382 if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
383 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
384 }
385 } ZEND_HASH_FOREACH_END();
386 }
387 smart_str_append_printf(str, "%s }\n", indent);
388
389 /* Static methods */
390 /* counting static methods */
391 count = zend_hash_num_elements(&ce->function_table);
392 if (count > 0) {
393 zend_function *mptr;
394
395 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
396 if (mptr->common.fn_flags & ZEND_ACC_STATIC
397 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
398 {
399 count_static_funcs++;
400 }
401 } ZEND_HASH_FOREACH_END();
402 }
403
404 /* static methods */
405 smart_str_append_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
406 if (count_static_funcs > 0) {
407 zend_function *mptr;
408
409 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
410 if (mptr->common.fn_flags & ZEND_ACC_STATIC
411 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
412 {
413 smart_str_append_printf(str, "\n");
414 _function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
415 }
416 } ZEND_HASH_FOREACH_END();
417 } else {
418 smart_str_append_printf(str, "\n");
419 }
420 smart_str_append_printf(str, "%s }\n", indent);
421
422 /* Default/Implicit properties */
423 count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
424 smart_str_append_printf(str, "\n%s - Properties [%d] {\n", indent, count);
425 if (count > 0) {
426 zend_property_info *prop;
427
428 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
429 if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
430 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
431 }
432 } ZEND_HASH_FOREACH_END();
433 }
434 smart_str_append_printf(str, "%s }\n", indent);
435
436 if (obj && Z_TYPE_P(obj) == IS_OBJECT && Z_OBJ_HT_P(obj)->get_properties) {
437 HashTable *properties = Z_OBJ_HT_P(obj)->get_properties(obj);
438 zend_string *prop_name;
439 smart_str prop_str = {0};
440
441 count = 0;
442 if (properties && zend_hash_num_elements(properties)) {
443 ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
444 if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
445 if (!zend_hash_exists(&ce->properties_info, prop_name)) {
446 count++;
447 _property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent));
448 }
449 }
450 } ZEND_HASH_FOREACH_END();
451 }
452
453 smart_str_append_printf(str, "\n%s - Dynamic properties [%d] {\n", indent, count);
454 smart_str_append_smart_str(str, &prop_str);
455 smart_str_append_printf(str, "%s }\n", indent);
456 smart_str_free(&prop_str);
457 }
458
459 /* Non static methods */
460 count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
461 if (count > 0) {
462 zend_function *mptr;
463 zend_string *key;
464 smart_str method_str = {0};
465
466 count = 0;
467 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
468 if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
469 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
470 {
471 size_t len = ZSTR_LEN(mptr->common.function_name);
472
473 /* Do not display old-style inherited constructors */
474 if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
475 || mptr->common.scope == ce
476 || !key
477 || zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0)
478 {
479 zend_function *closure;
480 /* see if this is a closure */
481 if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
482 && memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
483 && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
484 {
485 mptr = closure;
486 } else {
487 closure = NULL;
488 }
489 smart_str_appendc(&method_str, '\n');
490 _function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
491 count++;
492 _free_function(closure);
493 }
494 }
495 } ZEND_HASH_FOREACH_END();
496 smart_str_append_printf(str, "\n%s - Methods [%d] {", indent, count);
497 smart_str_append_smart_str(str, &method_str);
498 if (!count) {
499 smart_str_append_printf(str, "\n");
500 }
501 smart_str_free(&method_str);
502 } else {
503 smart_str_append_printf(str, "\n%s - Methods [0] {\n", indent);
504 }
505 smart_str_append_printf(str, "%s }\n", indent);
506
507 smart_str_append_printf(str, "%s}\n", indent);
508 zend_string_release_ex(sub_indent, 0);
509 }
510 /* }}} */
511
512 /* {{{ _const_string */
_const_string(smart_str * str,char * name,zval * value,char * indent)513 static void _const_string(smart_str *str, char *name, zval *value, char *indent)
514 {
515 char *type = zend_zval_type_name(value);
516
517 if (Z_TYPE_P(value) == IS_ARRAY) {
518 smart_str_append_printf(str, "%s Constant [ %s %s ] { Array }\n",
519 indent, type, name);
520 } else if (Z_TYPE_P(value) == IS_STRING) {
521 smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
522 indent, type, name, Z_STRVAL_P(value));
523 } else {
524 zend_string *tmp_value_str;
525 zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
526 smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
527 indent, type, name, ZSTR_VAL(value_str));
528 zend_tmp_string_release(tmp_value_str);
529 }
530 }
531 /* }}} */
532
533 /* {{{ _class_const_string */
_class_const_string(smart_str * str,char * name,zend_class_constant * c,char * indent)534 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char *indent)
535 {
536 char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
537 char *type;
538
539 zval_update_constant_ex(&c->value, c->ce);
540 type = zend_zval_type_name(&c->value);
541
542 if (Z_TYPE(c->value) == IS_ARRAY) {
543 smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
544 indent, visibility, type, name);
545 } else {
546 zend_string *tmp_value_str;
547 zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
548
549 smart_str_append_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
550 indent, visibility, type, name, ZSTR_VAL(value_str));
551
552 zend_tmp_string_release(tmp_value_str);
553 }
554 }
555 /* }}} */
556
557 /* {{{ _get_recv_opcode */
_get_recv_op(zend_op_array * op_array,uint32_t offset)558 static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
559 {
560 zend_op *op = op_array->opcodes;
561 zend_op *end = op + op_array->last;
562
563 ++offset;
564 while (op < end) {
565 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
566 || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
567 {
568 return op;
569 }
570 ++op;
571 }
572 return NULL;
573 }
574 /* }}} */
575
576 /* {{{ _parameter_string */
_parameter_string(smart_str * str,zend_function * fptr,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,char * indent)577 static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
578 {
579 smart_str_append_printf(str, "Parameter #%d [ ", offset);
580 if (!required) {
581 smart_str_append_printf(str, "<optional> ");
582 } else {
583 smart_str_append_printf(str, "<required> ");
584 }
585 if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
586 smart_str_append_printf(str, "%s ",
587 ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)));
588 if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
589 smart_str_append_printf(str, "or NULL ");
590 }
591 } else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
592 smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)));
593 if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
594 smart_str_append_printf(str, "or NULL ");
595 }
596 }
597 if (arg_info->pass_by_reference) {
598 smart_str_appendc(str, '&');
599 }
600 if (arg_info->is_variadic) {
601 smart_str_appends(str, "...");
602 }
603 if (arg_info->name) {
604 smart_str_append_printf(str, "$%s",
605 (fptr->type == ZEND_INTERNAL_FUNCTION &&
606 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
607 ((zend_internal_arg_info*)arg_info)->name :
608 ZSTR_VAL(arg_info->name));
609 } else {
610 smart_str_append_printf(str, "$param%d", offset);
611 }
612 if (fptr->type == ZEND_USER_FUNCTION && !required) {
613 zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
614 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
615 zval zv;
616
617 smart_str_appends(str, " = ");
618 ZVAL_COPY(&zv, RT_CONSTANT(precv, precv->op2));
619 if (UNEXPECTED(zval_update_constant_ex(&zv, fptr->common.scope) == FAILURE)) {
620 zval_ptr_dtor(&zv);
621 return;
622 }
623 if (Z_TYPE(zv) == IS_TRUE) {
624 smart_str_appends(str, "true");
625 } else if (Z_TYPE(zv) == IS_FALSE) {
626 smart_str_appends(str, "false");
627 } else if (Z_TYPE(zv) == IS_NULL) {
628 smart_str_appends(str, "NULL");
629 } else if (Z_TYPE(zv) == IS_STRING) {
630 smart_str_appendc(str, '\'');
631 smart_str_appendl(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
632 if (Z_STRLEN(zv) > 15) {
633 smart_str_appends(str, "...");
634 }
635 smart_str_appendc(str, '\'');
636 } else if (Z_TYPE(zv) == IS_ARRAY) {
637 smart_str_appends(str, "Array");
638 } else {
639 zend_string *tmp_zv_str;
640 zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
641 smart_str_append(str, zv_str);
642 zend_tmp_string_release(tmp_zv_str);
643 }
644 zval_ptr_dtor(&zv);
645 }
646 }
647 smart_str_appends(str, " ]");
648 }
649 /* }}} */
650
651 /* {{{ _function_parameter_string */
_function_parameter_string(smart_str * str,zend_function * fptr,char * indent)652 static void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
653 {
654 struct _zend_arg_info *arg_info = fptr->common.arg_info;
655 uint32_t i, num_args, num_required = fptr->common.required_num_args;
656
657 if (!arg_info) {
658 return;
659 }
660
661 num_args = fptr->common.num_args;
662 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
663 num_args++;
664 }
665 smart_str_appendc(str, '\n');
666 smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
667 for (i = 0; i < num_args; i++) {
668 smart_str_append_printf(str, "%s ", indent);
669 _parameter_string(str, fptr, arg_info, i, i < num_required, indent);
670 smart_str_appendc(str, '\n');
671 arg_info++;
672 }
673 smart_str_append_printf(str, "%s}\n", indent);
674 }
675 /* }}} */
676
677 /* {{{ _function_closure_string */
_function_closure_string(smart_str * str,zend_function * fptr,char * indent)678 static void _function_closure_string(smart_str *str, zend_function *fptr, char* indent)
679 {
680 uint32_t i, count;
681 zend_string *key;
682 HashTable *static_variables;
683
684 if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
685 return;
686 }
687
688 static_variables = fptr->op_array.static_variables;
689 count = zend_hash_num_elements(static_variables);
690
691 if (!count) {
692 return;
693 }
694
695 smart_str_append_printf(str, "\n");
696 smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
697 i = 0;
698 ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
699 smart_str_append_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
700 } ZEND_HASH_FOREACH_END();
701 smart_str_append_printf(str, "%s}\n", indent);
702 }
703 /* }}} */
704
705 /* {{{ _function_string */
_function_string(smart_str * str,zend_function * fptr,zend_class_entry * scope,char * indent)706 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent)
707 {
708 smart_str param_indent = {0};
709 zend_function *overwrites;
710 zend_string *lc_name;
711
712 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
713 * What's "wrong" is that any whitespace before the doc comment start is
714 * swallowed, leading to an unaligned comment.
715 */
716 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
717 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
718 }
719
720 smart_str_appendl(str, indent, strlen(indent));
721 smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
722 smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
723 if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
724 smart_str_appends(str, ", deprecated");
725 }
726 if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
727 smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
728 }
729
730 if (scope && fptr->common.scope) {
731 if (fptr->common.scope != scope) {
732 smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
733 } else if (fptr->common.scope->parent) {
734 lc_name = zend_string_tolower(fptr->common.function_name);
735 if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
736 if (fptr->common.scope != overwrites->common.scope) {
737 smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
738 }
739 }
740 zend_string_release_ex(lc_name, 0);
741 }
742 }
743 if (fptr->common.prototype && fptr->common.prototype->common.scope) {
744 smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
745 }
746 if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
747 smart_str_appends(str, ", ctor");
748 }
749 if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
750 smart_str_appends(str, ", dtor");
751 }
752 smart_str_appends(str, "> ");
753
754 if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
755 smart_str_appends(str, "abstract ");
756 }
757 if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
758 smart_str_appends(str, "final ");
759 }
760 if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
761 smart_str_appends(str, "static ");
762 }
763
764 if (fptr->common.scope) {
765 /* These are mutually exclusive */
766 switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
767 case ZEND_ACC_PUBLIC:
768 smart_str_appends(str, "public ");
769 break;
770 case ZEND_ACC_PRIVATE:
771 smart_str_appends(str, "private ");
772 break;
773 case ZEND_ACC_PROTECTED:
774 smart_str_appends(str, "protected ");
775 break;
776 default:
777 smart_str_appends(str, "<visibility error> ");
778 break;
779 }
780 smart_str_appends(str, "method ");
781 } else {
782 smart_str_appends(str, "function ");
783 }
784
785 if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
786 smart_str_appendc(str, '&');
787 }
788 smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
789 /* The information where a function is declared is only available for user classes */
790 if (fptr->type == ZEND_USER_FUNCTION) {
791 smart_str_append_printf(str, "%s @@ %s %d - %d\n", indent,
792 ZSTR_VAL(fptr->op_array.filename),
793 fptr->op_array.line_start,
794 fptr->op_array.line_end);
795 }
796 smart_str_append_printf(¶m_indent, "%s ", indent);
797 smart_str_0(¶m_indent);
798 if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
799 _function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
800 }
801 _function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
802 smart_str_free(¶m_indent);
803 if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
804 smart_str_append_printf(str, " %s- Return [ ", indent);
805 if (ZEND_TYPE_IS_CLASS(fptr->common.arg_info[-1].type)) {
806 smart_str_append_printf(str, "%s ",
807 ZSTR_VAL(ZEND_TYPE_NAME(fptr->common.arg_info[-1].type)));
808 if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
809 smart_str_appends(str, "or NULL ");
810 }
811 } else if (ZEND_TYPE_IS_CODE(fptr->common.arg_info[-1].type)) {
812 smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(fptr->common.arg_info[-1].type)));
813 if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
814 smart_str_appends(str, "or NULL ");
815 }
816 }
817 smart_str_appends(str, "]\n");
818 }
819 smart_str_append_printf(str, "%s}\n", indent);
820 }
821 /* }}} */
822
823 /* {{{ _property_string */
_property_string(smart_str * str,zend_property_info * prop,const char * prop_name,char * indent)824 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent)
825 {
826 smart_str_append_printf(str, "%sProperty [ ", indent);
827 if (!prop) {
828 smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
829 } else {
830 if (!(prop->flags & ZEND_ACC_STATIC)) {
831 if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
832 smart_str_appends(str, "<implicit> ");
833 } else {
834 smart_str_appends(str, "<default> ");
835 }
836 }
837
838 /* These are mutually exclusive */
839 switch (prop->flags & ZEND_ACC_PPP_MASK) {
840 case ZEND_ACC_PUBLIC:
841 smart_str_appends(str, "public ");
842 break;
843 case ZEND_ACC_PRIVATE:
844 smart_str_appends(str, "private ");
845 break;
846 case ZEND_ACC_PROTECTED:
847 smart_str_appends(str, "protected ");
848 break;
849 }
850 if (prop->flags & ZEND_ACC_STATIC) {
851 smart_str_appends(str, "static ");
852 }
853 if (!prop_name) {
854 const char *class_name;
855 zend_unmangle_property_name(prop->name, &class_name, &prop_name);
856 }
857 smart_str_append_printf(str, "$%s", prop_name);
858 }
859
860 smart_str_appends(str, " ]\n");
861 }
862 /* }}} */
863
_extension_ini_string(zval * el,int num_args,va_list args,zend_hash_key * hash_key)864 static int _extension_ini_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
865 {
866 zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
867 smart_str *str = va_arg(args, smart_str *);
868 char *indent = va_arg(args, char *);
869 int number = va_arg(args, int);
870 char *comma = "";
871
872 if (number == ini_entry->module_number) {
873 smart_str_append_printf(str, " %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
874 if (ini_entry->modifiable == ZEND_INI_ALL) {
875 smart_str_appends(str, "ALL");
876 } else {
877 if (ini_entry->modifiable & ZEND_INI_USER) {
878 smart_str_appends(str, "USER");
879 comma = ",";
880 }
881 if (ini_entry->modifiable & ZEND_INI_PERDIR) {
882 smart_str_append_printf(str, "%sPERDIR", comma);
883 comma = ",";
884 }
885 if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
886 smart_str_append_printf(str, "%sSYSTEM", comma);
887 }
888 }
889
890 smart_str_appends(str, "> ]\n");
891 smart_str_append_printf(str, " %s Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
892 if (ini_entry->modified) {
893 smart_str_append_printf(str, " %s Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
894 }
895 smart_str_append_printf(str, " %s}\n", indent);
896 }
897 return ZEND_HASH_APPLY_KEEP;
898 }
899 /* }}} */
900
_extension_class_string(zval * el,int num_args,va_list args,zend_hash_key * hash_key)901 static int _extension_class_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
902 {
903 zend_class_entry *ce = (zend_class_entry*)Z_PTR_P(el);
904 smart_str *str = va_arg(args, smart_str *);
905 char *indent = va_arg(args, char *);
906 struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
907 int *num_classes = va_arg(args, int*);
908
909 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
910 /* dump class if it is not an alias */
911 if (!zend_binary_strcasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key))) {
912 smart_str_append_printf(str, "\n");
913 _class_string(str, ce, NULL, indent);
914 (*num_classes)++;
915 }
916 }
917 return ZEND_HASH_APPLY_KEEP;
918 }
919 /* }}} */
920
_extension_const_string(zval * el,int num_args,va_list args,zend_hash_key * hash_key)921 static int _extension_const_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
922 {
923 zend_constant *constant = (zend_constant*)Z_PTR_P(el);
924 smart_str *str = va_arg(args, smart_str *);
925 char *indent = va_arg(args, char *);
926 struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
927 int *num_classes = va_arg(args, int*);
928
929 if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
930 _const_string(str, ZSTR_VAL(constant->name), &constant->value, indent);
931 (*num_classes)++;
932 }
933 return ZEND_HASH_APPLY_KEEP;
934 }
935 /* }}} */
936
_extension_string(smart_str * str,zend_module_entry * module,char * indent)937 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent) /* {{{ */
938 {
939 smart_str_append_printf(str, "%sExtension [ ", indent);
940 if (module->type == MODULE_PERSISTENT) {
941 smart_str_appends(str, "<persistent>");
942 }
943 if (module->type == MODULE_TEMPORARY) {
944 smart_str_appends(str, "<temporary>" );
945 }
946 smart_str_append_printf(str, " extension #%d %s version %s ] {\n",
947 module->module_number, module->name,
948 (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
949
950 if (module->deps) {
951 const zend_module_dep* dep = module->deps;
952
953 smart_str_appends(str, "\n - Dependencies {\n");
954
955 while(dep->name) {
956 smart_str_append_printf(str, "%s Dependency [ %s (", indent, dep->name);
957
958 switch(dep->type) {
959 case MODULE_DEP_REQUIRED:
960 smart_str_appends(str, "Required");
961 break;
962 case MODULE_DEP_CONFLICTS:
963 smart_str_appends(str, "Conflicts");
964 break;
965 case MODULE_DEP_OPTIONAL:
966 smart_str_appends(str, "Optional");
967 break;
968 default:
969 smart_str_appends(str, "Error"); /* shouldn't happen */
970 break;
971 }
972
973 if (dep->rel) {
974 smart_str_append_printf(str, " %s", dep->rel);
975 }
976 if (dep->version) {
977 smart_str_append_printf(str, " %s", dep->version);
978 }
979 smart_str_appends(str, ") ]\n");
980 dep++;
981 }
982 smart_str_append_printf(str, "%s }\n", indent);
983 }
984
985 {
986 smart_str str_ini = {0};
987 zend_hash_apply_with_arguments(EG(ini_directives), (apply_func_args_t) _extension_ini_string, 3, &str_ini, indent, module->module_number);
988 if (smart_str_get_len(&str_ini) > 0) {
989 smart_str_append_printf(str, "\n - INI {\n");
990 smart_str_append_smart_str(str, &str_ini);
991 smart_str_append_printf(str, "%s }\n", indent);
992 }
993 smart_str_free(&str_ini);
994 }
995
996 {
997 smart_str str_constants = {0};
998 int num_constants = 0;
999
1000 zend_hash_apply_with_arguments(EG(zend_constants), (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
1001 if (num_constants) {
1002 smart_str_append_printf(str, "\n - Constants [%d] {\n", num_constants);
1003 smart_str_append_smart_str(str, &str_constants);
1004 smart_str_append_printf(str, "%s }\n", indent);
1005 }
1006 smart_str_free(&str_constants);
1007 }
1008
1009 {
1010 zend_function *fptr;
1011 int first = 1;
1012
1013 ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
1014 if (fptr->common.type==ZEND_INTERNAL_FUNCTION
1015 && fptr->internal_function.module == module) {
1016 if (first) {
1017 smart_str_append_printf(str, "\n - Functions {\n");
1018 first = 0;
1019 }
1020 _function_string(str, fptr, NULL, " ");
1021 }
1022 } ZEND_HASH_FOREACH_END();
1023 if (!first) {
1024 smart_str_append_printf(str, "%s }\n", indent);
1025 }
1026 }
1027
1028 {
1029 zend_string *sub_indent = strpprintf(0, "%s ", indent);
1030 smart_str str_classes = {0};
1031 int num_classes = 0;
1032
1033 zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) _extension_class_string, 4, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes);
1034 if (num_classes) {
1035 smart_str_append_printf(str, "\n - Classes [%d] {", num_classes);
1036 smart_str_append_smart_str(str, &str_classes);
1037 smart_str_append_printf(str, "%s }\n", indent);
1038 }
1039 smart_str_free(&str_classes);
1040 zend_string_release_ex(sub_indent, 0);
1041 }
1042
1043 smart_str_append_printf(str, "%s}\n", indent);
1044 }
1045 /* }}} */
1046
_zend_extension_string(smart_str * str,zend_extension * extension,char * indent)1047 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent) /* {{{ */
1048 {
1049 smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
1050
1051 if (extension->version) {
1052 smart_str_append_printf(str, "%s ", extension->version);
1053 }
1054 if (extension->copyright) {
1055 smart_str_append_printf(str, "%s ", extension->copyright);
1056 }
1057 if (extension->author) {
1058 smart_str_append_printf(str, "by %s ", extension->author);
1059 }
1060 if (extension->URL) {
1061 smart_str_append_printf(str, "<%s> ", extension->URL);
1062 }
1063
1064 smart_str_appends(str, "]\n");
1065 }
1066 /* }}} */
1067
1068 /* {{{ _function_check_flag */
_function_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)1069 static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
1070 {
1071 reflection_object *intern;
1072 zend_function *mptr;
1073
1074 if (zend_parse_parameters_none() == FAILURE) {
1075 return;
1076 }
1077 GET_REFLECTION_OBJECT_PTR(mptr);
1078 RETURN_BOOL(mptr->common.fn_flags & mask);
1079 }
1080 /* }}} */
1081
1082 /* {{{ zend_reflection_class_factory */
zend_reflection_class_factory(zend_class_entry * ce,zval * object)1083 PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
1084 {
1085 reflection_object *intern;
1086 zval name;
1087
1088 ZVAL_STR_COPY(&name, ce->name);
1089 reflection_instantiate(reflection_class_ptr, object);
1090 intern = Z_REFLECTION_P(object);
1091 intern->ptr = ce;
1092 intern->ref_type = REF_TYPE_OTHER;
1093 intern->ce = ce;
1094 reflection_update_property_name(object, &name);
1095 }
1096 /* }}} */
1097
1098 /* {{{ reflection_extension_factory */
reflection_extension_factory(zval * object,const char * name_str)1099 static void reflection_extension_factory(zval *object, const char *name_str)
1100 {
1101 reflection_object *intern;
1102 zval name;
1103 size_t name_len = strlen(name_str);
1104 zend_string *lcname;
1105 struct _zend_module_entry *module;
1106
1107 lcname = zend_string_alloc(name_len, 0);
1108 zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
1109 module = zend_hash_find_ptr(&module_registry, lcname);
1110 zend_string_efree(lcname);
1111 if (!module) {
1112 return;
1113 }
1114
1115 reflection_instantiate(reflection_extension_ptr, object);
1116 intern = Z_REFLECTION_P(object);
1117 ZVAL_STRINGL(&name, module->name, name_len);
1118 intern->ptr = module;
1119 intern->ref_type = REF_TYPE_OTHER;
1120 intern->ce = NULL;
1121 reflection_update_property_name(object, &name);
1122 }
1123 /* }}} */
1124
1125 /* {{{ reflection_parameter_factory */
reflection_parameter_factory(zend_function * fptr,zval * closure_object,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,zval * object)1126 static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, zval *object)
1127 {
1128 reflection_object *intern;
1129 parameter_reference *reference;
1130 zval name;
1131
1132 if (arg_info->name) {
1133 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
1134 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
1135 ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)->name);
1136 } else {
1137 ZVAL_STR_COPY(&name, arg_info->name);
1138 }
1139 } else {
1140 ZVAL_NULL(&name);
1141 }
1142 reflection_instantiate(reflection_parameter_ptr, object);
1143 intern = Z_REFLECTION_P(object);
1144 reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
1145 reference->arg_info = arg_info;
1146 reference->offset = offset;
1147 reference->required = required;
1148 reference->fptr = fptr;
1149 intern->ptr = reference;
1150 intern->ref_type = REF_TYPE_PARAMETER;
1151 intern->ce = fptr->common.scope;
1152 if (closure_object) {
1153 Z_ADDREF_P(closure_object);
1154 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1155 }
1156 reflection_update_property_name(object, &name);
1157 }
1158 /* }}} */
1159
1160 /* {{{ reflection_type_factory */
reflection_type_factory(zend_function * fptr,zval * closure_object,struct _zend_arg_info * arg_info,zval * object)1161 static void reflection_type_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, zval *object)
1162 {
1163 reflection_object *intern;
1164 type_reference *reference;
1165
1166 reflection_instantiate(reflection_named_type_ptr, object);
1167 intern = Z_REFLECTION_P(object);
1168 reference = (type_reference*) emalloc(sizeof(type_reference));
1169 reference->arg_info = arg_info;
1170 reference->fptr = fptr;
1171 intern->ptr = reference;
1172 intern->ref_type = REF_TYPE_TYPE;
1173 intern->ce = fptr->common.scope;
1174 if (closure_object) {
1175 Z_ADDREF_P(closure_object);
1176 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1177 }
1178 }
1179 /* }}} */
1180
1181 /* {{{ reflection_function_factory */
reflection_function_factory(zend_function * function,zval * closure_object,zval * object)1182 static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
1183 {
1184 reflection_object *intern;
1185 zval name;
1186
1187 ZVAL_STR_COPY(&name, function->common.function_name);
1188
1189 reflection_instantiate(reflection_function_ptr, object);
1190 intern = Z_REFLECTION_P(object);
1191 intern->ptr = function;
1192 intern->ref_type = REF_TYPE_FUNCTION;
1193 intern->ce = NULL;
1194 if (closure_object) {
1195 Z_ADDREF_P(closure_object);
1196 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1197 }
1198 reflection_update_property_name(object, &name);
1199 }
1200 /* }}} */
1201
1202 /* {{{ reflection_method_factory */
reflection_method_factory(zend_class_entry * ce,zend_function * method,zval * closure_object,zval * object)1203 static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
1204 {
1205 reflection_object *intern;
1206 zval name;
1207 zval classname;
1208
1209 ZVAL_STR_COPY(&name, (method->common.scope && method->common.scope->trait_aliases)?
1210 zend_resolve_method_name(ce, method) : method->common.function_name);
1211 ZVAL_STR_COPY(&classname, method->common.scope->name);
1212 reflection_instantiate(reflection_method_ptr, object);
1213 intern = Z_REFLECTION_P(object);
1214 intern->ptr = method;
1215 intern->ref_type = REF_TYPE_FUNCTION;
1216 intern->ce = ce;
1217 if (closure_object) {
1218 Z_ADDREF_P(closure_object);
1219 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1220 }
1221 reflection_update_property_name(object, &name);
1222 reflection_update_property_class(object, &classname);
1223 }
1224 /* }}} */
1225
1226 /* {{{ reflection_property_factory */
reflection_property_factory(zend_class_entry * ce,zend_string * name,zend_property_info * prop,zval * object)1227 static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object)
1228 {
1229 reflection_object *intern;
1230 zval propname;
1231 zval classname;
1232 property_reference *reference;
1233
1234 if (!(prop->flags & ZEND_ACC_PRIVATE)) {
1235 /* we have to search the class hierarchy for this (implicit) public or protected property */
1236 zend_class_entry *tmp_ce = ce, *store_ce = ce;
1237 zend_property_info *tmp_info = NULL;
1238
1239 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
1240 ce = tmp_ce;
1241 tmp_ce = tmp_ce->parent;
1242 }
1243
1244 if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
1245 prop = tmp_info;
1246 } else { /* not found, use initial value */
1247 ce = store_ce;
1248 }
1249 }
1250
1251 ZVAL_STR_COPY(&propname, name);
1252 ZVAL_STR_COPY(&classname, prop->ce->name);
1253
1254 reflection_instantiate(reflection_property_ptr, object);
1255 intern = Z_REFLECTION_P(object);
1256 reference = (property_reference*) emalloc(sizeof(property_reference));
1257 reference->ce = ce;
1258 reference->prop = *prop;
1259 reference->unmangled_name = zend_string_copy(name);
1260 intern->ptr = reference;
1261 intern->ref_type = REF_TYPE_PROPERTY;
1262 intern->ce = ce;
1263 intern->ignore_visibility = 0;
1264 reflection_update_property_name(object, &propname);
1265 reflection_update_property_class(object, &classname);
1266 }
1267 /* }}} */
1268
reflection_property_factory_str(zend_class_entry * ce,const char * name_str,size_t name_len,zend_property_info * prop,zval * object)1269 static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
1270 {
1271 zend_string *name = zend_string_init(name_str, name_len, 0);
1272 reflection_property_factory(ce, name, prop, object);
1273 zend_string_release(name);
1274 }
1275
1276 /* {{{ reflection_class_constant_factory */
reflection_class_constant_factory(zend_class_entry * ce,zend_string * name_str,zend_class_constant * constant,zval * object)1277 static void reflection_class_constant_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
1278 {
1279 reflection_object *intern;
1280 zval name;
1281 zval classname;
1282
1283 ZVAL_STR_COPY(&name, name_str);
1284 ZVAL_STR_COPY(&classname, ce->name);
1285
1286 reflection_instantiate(reflection_class_constant_ptr, object);
1287 intern = Z_REFLECTION_P(object);
1288 intern->ptr = constant;
1289 intern->ref_type = REF_TYPE_CLASS_CONSTANT;
1290 intern->ce = constant->ce;
1291 intern->ignore_visibility = 0;
1292 reflection_update_property_name(object, &name);
1293 reflection_update_property_class(object, &classname);
1294 }
1295 /* }}} */
1296
1297 /* {{{ _reflection_export */
_reflection_export(INTERNAL_FUNCTION_PARAMETERS,zend_class_entry * ce_ptr,int ctor_argc)1298 static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
1299 {
1300 zval reflector;
1301 zval *argument_ptr, *argument2_ptr;
1302 zval retval, params[2];
1303 int result;
1304 int return_output = 0;
1305 zend_fcall_info fci;
1306 zend_fcall_info_cache fcc;
1307
1308 if (ctor_argc == 1) {
1309 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &argument_ptr, &return_output) == FAILURE) {
1310 return;
1311 }
1312 ZVAL_COPY_VALUE(¶ms[0], argument_ptr);
1313 ZVAL_NULL(¶ms[1]);
1314 } else {
1315 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
1316 return;
1317 }
1318 ZVAL_COPY_VALUE(¶ms[0], argument_ptr);
1319 ZVAL_COPY_VALUE(¶ms[1], argument2_ptr);
1320 }
1321
1322 /* Create object */
1323 if (object_and_properties_init(&reflector, ce_ptr, NULL) == FAILURE) {
1324 _DO_THROW("Could not create reflector");
1325 }
1326
1327 /* Call __construct() */
1328
1329 fci.size = sizeof(fci);
1330 ZVAL_UNDEF(&fci.function_name);
1331 fci.object = Z_OBJ(reflector);
1332 fci.retval = &retval;
1333 fci.param_count = ctor_argc;
1334 fci.params = params;
1335 fci.no_separation = 1;
1336
1337 fcc.function_handler = ce_ptr->constructor;
1338 fcc.called_scope = Z_OBJCE(reflector);
1339 fcc.object = Z_OBJ(reflector);
1340
1341 result = zend_call_function(&fci, &fcc);
1342
1343 zval_ptr_dtor(&retval);
1344
1345 if (EG(exception)) {
1346 zval_ptr_dtor(&reflector);
1347 return;
1348 }
1349 if (result == FAILURE) {
1350 zval_ptr_dtor(&reflector);
1351 _DO_THROW("Could not create reflector");
1352 }
1353
1354 /* Call static reflection::export */
1355 ZVAL_COPY_VALUE(¶ms[0], &reflector);
1356 ZVAL_BOOL(¶ms[1], return_output);
1357
1358 ZVAL_STRINGL(&fci.function_name, "reflection::export", sizeof("reflection::export") - 1);
1359 fci.object = NULL;
1360 fci.retval = &retval;
1361 fci.param_count = 2;
1362 fci.params = params;
1363 fci.no_separation = 1;
1364
1365 result = zend_call_function(&fci, NULL);
1366
1367 zval_ptr_dtor(&fci.function_name);
1368
1369 if (result == FAILURE && EG(exception) == NULL) {
1370 zval_ptr_dtor(&reflector);
1371 zval_ptr_dtor(&retval);
1372 _DO_THROW("Could not execute reflection::export()");
1373 }
1374
1375 if (return_output) {
1376 ZVAL_COPY_VALUE(return_value, &retval);
1377 } else {
1378 zval_ptr_dtor(&retval);
1379 }
1380
1381 /* Destruct reflector which is no longer needed */
1382 zval_ptr_dtor(&reflector);
1383 }
1384 /* }}} */
1385
1386 /* {{{ _reflection_param_get_default_param */
_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)1387 static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)
1388 {
1389 reflection_object *intern;
1390 parameter_reference *param;
1391
1392 intern = Z_REFLECTION_P(getThis());
1393 if (intern->ptr == NULL) {
1394 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {
1395 return NULL;
1396 }
1397 zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object");
1398 return NULL;
1399 }
1400
1401 param = intern->ptr;
1402 if (param->fptr->type != ZEND_USER_FUNCTION) {
1403 zend_throw_exception_ex(reflection_exception_ptr, 0, "Cannot determine default value for internal functions");
1404 return NULL;
1405 }
1406
1407 return param;
1408 }
1409 /* }}} */
1410
1411 /* {{{ _reflection_param_get_default_precv */
_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS,parameter_reference * param)1412 static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS, parameter_reference *param)
1413 {
1414 zend_op *precv;
1415
1416 if (param == NULL) {
1417 return NULL;
1418 }
1419
1420 precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
1421 if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
1422 zend_throw_exception_ex(reflection_exception_ptr, 0, "Internal error: Failed to retrieve the default value");
1423 return NULL;
1424 }
1425
1426 return precv;
1427 }
1428 /* }}} */
1429
1430 /* {{{ Preventing __clone from being called */
ZEND_METHOD(reflection,__clone)1431 ZEND_METHOD(reflection, __clone)
1432 {
1433 /* Should never be executable */
1434 _DO_THROW("Cannot clone object using __clone()");
1435 }
1436 /* }}} */
1437
1438 /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
1439 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection,export)1440 ZEND_METHOD(reflection, export)
1441 {
1442 zval *object, fname, retval;
1443 int result;
1444 zend_bool return_output = 0;
1445
1446 ZEND_PARSE_PARAMETERS_START(1, 2)
1447 Z_PARAM_OBJECT_OF_CLASS(object, reflector_ptr)
1448 Z_PARAM_OPTIONAL
1449 Z_PARAM_BOOL(return_output)
1450 ZEND_PARSE_PARAMETERS_END();
1451
1452 /* Invoke the __toString() method */
1453 ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1);
1454 result= call_user_function(NULL, object, &fname, &retval, 0, NULL);
1455 zval_ptr_dtor_str(&fname);
1456
1457 if (result == FAILURE) {
1458 _DO_THROW("Invocation of method __toString() failed");
1459 /* Returns from this function */
1460 }
1461
1462 if (Z_TYPE(retval) == IS_UNDEF) {
1463 php_error_docref(NULL, E_WARNING, "%s::__toString() did not return anything", ZSTR_VAL(Z_OBJCE_P(object)->name));
1464 RETURN_FALSE;
1465 }
1466
1467 if (return_output) {
1468 ZVAL_COPY_VALUE(return_value, &retval);
1469 } else {
1470 /* No need for _r variant, return of __toString should always be a string */
1471 zend_print_zval(&retval, 0);
1472 zend_printf("\n");
1473 zval_ptr_dtor(&retval);
1474 }
1475 }
1476 /* }}} */
1477
1478 /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
1479 Returns an array of modifier names */
ZEND_METHOD(reflection,getModifierNames)1480 ZEND_METHOD(reflection, getModifierNames)
1481 {
1482 zend_long modifiers;
1483
1484 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
1485 return;
1486 }
1487
1488 array_init(return_value);
1489
1490 if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1491 add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
1492 }
1493 if (modifiers & ZEND_ACC_FINAL) {
1494 add_next_index_stringl(return_value, "final", sizeof("final")-1);
1495 }
1496 if (modifiers & ZEND_ACC_IMPLICIT_PUBLIC) {
1497 add_next_index_stringl(return_value, "public", sizeof("public")-1);
1498 }
1499
1500 /* These are mutually exclusive */
1501 switch (modifiers & ZEND_ACC_PPP_MASK) {
1502 case ZEND_ACC_PUBLIC:
1503 add_next_index_stringl(return_value, "public", sizeof("public")-1);
1504 break;
1505 case ZEND_ACC_PRIVATE:
1506 add_next_index_stringl(return_value, "private", sizeof("private")-1);
1507 break;
1508 case ZEND_ACC_PROTECTED:
1509 add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
1510 break;
1511 }
1512
1513 if (modifiers & ZEND_ACC_STATIC) {
1514 add_next_index_stringl(return_value, "static", sizeof("static")-1);
1515 }
1516 }
1517 /* }}} */
1518
1519 /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
1520 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_function,export)1521 ZEND_METHOD(reflection_function, export)
1522 {
1523 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
1524 }
1525 /* }}} */
1526
1527 /* {{{ proto public void ReflectionFunction::__construct(string name)
1528 Constructor. Throws an Exception in case the given function does not exist */
ZEND_METHOD(reflection_function,__construct)1529 ZEND_METHOD(reflection_function, __construct)
1530 {
1531 zval name;
1532 zval *object;
1533 zval *closure = NULL;
1534 reflection_object *intern;
1535 zend_function *fptr;
1536 zend_string *fname, *lcname;
1537
1538 object = getThis();
1539 intern = Z_REFLECTION_P(object);
1540
1541 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
1542 fptr = (zend_function*)zend_get_closure_method_def(closure);
1543 Z_ADDREF_P(closure);
1544 } else {
1545 ALLOCA_FLAG(use_heap)
1546
1547 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "S", &fname) == FAILURE) {
1548 return;
1549 }
1550
1551 if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
1552 /* Ignore leading "\" */
1553 ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
1554 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
1555 fptr = zend_fetch_function(lcname);
1556 ZSTR_ALLOCA_FREE(lcname, use_heap);
1557 } else {
1558 lcname = zend_string_tolower(fname);
1559 fptr = zend_fetch_function(lcname);
1560 zend_string_release(lcname);
1561 }
1562
1563 if (fptr == NULL) {
1564 zend_throw_exception_ex(reflection_exception_ptr, 0,
1565 "Function %s() does not exist", ZSTR_VAL(fname));
1566 return;
1567 }
1568 }
1569
1570 ZVAL_STR_COPY(&name, fptr->common.function_name);
1571 reflection_update_property_name(object, &name);
1572 intern->ptr = fptr;
1573 intern->ref_type = REF_TYPE_FUNCTION;
1574 if (closure) {
1575 ZVAL_COPY_VALUE(&intern->obj, closure);
1576 } else {
1577 ZVAL_UNDEF(&intern->obj);
1578 }
1579 intern->ce = NULL;
1580 }
1581 /* }}} */
1582
1583 /* {{{ proto public string ReflectionFunction::__toString()
1584 Returns a string representation */
ZEND_METHOD(reflection_function,__toString)1585 ZEND_METHOD(reflection_function, __toString)
1586 {
1587 reflection_object *intern;
1588 zend_function *fptr;
1589 smart_str str = {0};
1590
1591 if (zend_parse_parameters_none() == FAILURE) {
1592 return;
1593 }
1594 GET_REFLECTION_OBJECT_PTR(fptr);
1595 _function_string(&str, fptr, intern->ce, "");
1596 RETURN_STR(smart_str_extract(&str));
1597 }
1598 /* }}} */
1599
1600 /* {{{ proto public string ReflectionFunction::getName()
1601 Returns this function's name */
ZEND_METHOD(reflection_function,getName)1602 ZEND_METHOD(reflection_function, getName)
1603 {
1604 if (zend_parse_parameters_none() == FAILURE) {
1605 return;
1606 }
1607 _default_get_name(getThis(), return_value);
1608 }
1609 /* }}} */
1610
1611 /* {{{ proto public bool ReflectionFunction::isClosure()
1612 Returns whether this is a closure */
ZEND_METHOD(reflection_function,isClosure)1613 ZEND_METHOD(reflection_function, isClosure)
1614 {
1615 reflection_object *intern;
1616 zend_function *fptr;
1617
1618 if (zend_parse_parameters_none() == FAILURE) {
1619 return;
1620 }
1621 GET_REFLECTION_OBJECT_PTR(fptr);
1622 RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
1623 }
1624 /* }}} */
1625
1626 /* {{{ proto public bool ReflectionFunction::getClosureThis()
1627 Returns this pointer bound to closure */
ZEND_METHOD(reflection_function,getClosureThis)1628 ZEND_METHOD(reflection_function, getClosureThis)
1629 {
1630 reflection_object *intern;
1631 zval* closure_this;
1632
1633 if (zend_parse_parameters_none() == FAILURE) {
1634 return;
1635 }
1636 GET_REFLECTION_OBJECT();
1637 if (!Z_ISUNDEF(intern->obj)) {
1638 closure_this = zend_get_closure_this_ptr(&intern->obj);
1639 if (!Z_ISUNDEF_P(closure_this)) {
1640 ZVAL_COPY(return_value, closure_this);
1641 }
1642 }
1643 }
1644 /* }}} */
1645
1646 /* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
1647 Returns the scope associated to the closure */
ZEND_METHOD(reflection_function,getClosureScopeClass)1648 ZEND_METHOD(reflection_function, getClosureScopeClass)
1649 {
1650 reflection_object *intern;
1651 const zend_function *closure_func;
1652
1653 if (zend_parse_parameters_none() == FAILURE) {
1654 return;
1655 }
1656 GET_REFLECTION_OBJECT();
1657 if (!Z_ISUNDEF(intern->obj)) {
1658 closure_func = zend_get_closure_method_def(&intern->obj);
1659 if (closure_func && closure_func->common.scope) {
1660 zend_reflection_class_factory(closure_func->common.scope, return_value);
1661 }
1662 }
1663 }
1664 /* }}} */
1665
1666 /* {{{ proto public mixed ReflectionFunction::getClosure()
1667 Returns a dynamically created closure for the function */
ZEND_METHOD(reflection_function,getClosure)1668 ZEND_METHOD(reflection_function, getClosure)
1669 {
1670 reflection_object *intern;
1671 zend_function *fptr;
1672
1673 if (zend_parse_parameters_none() == FAILURE) {
1674 return;
1675 }
1676 GET_REFLECTION_OBJECT_PTR(fptr);
1677
1678 if (!Z_ISUNDEF(intern->obj)) {
1679 /* Closures are immutable objects */
1680 ZVAL_COPY(return_value, &intern->obj);
1681 } else {
1682 zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
1683 }
1684 }
1685 /* }}} */
1686
1687 /* {{{ proto public bool ReflectionFunction::isInternal()
1688 Returns whether this is an internal function */
ZEND_METHOD(reflection_function,isInternal)1689 ZEND_METHOD(reflection_function, isInternal)
1690 {
1691 reflection_object *intern;
1692 zend_function *fptr;
1693
1694 if (zend_parse_parameters_none() == FAILURE) {
1695 return;
1696 }
1697 GET_REFLECTION_OBJECT_PTR(fptr);
1698 RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
1699 }
1700 /* }}} */
1701
1702 /* {{{ proto public bool ReflectionFunction::isUserDefined()
1703 Returns whether this is a user-defined function */
ZEND_METHOD(reflection_function,isUserDefined)1704 ZEND_METHOD(reflection_function, isUserDefined)
1705 {
1706 reflection_object *intern;
1707 zend_function *fptr;
1708
1709 if (zend_parse_parameters_none() == FAILURE) {
1710 return;
1711 }
1712 GET_REFLECTION_OBJECT_PTR(fptr);
1713 RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
1714 }
1715 /* }}} */
1716
1717 /* {{{ proto public bool ReflectionFunction::isDisabled()
1718 Returns whether this function has been disabled or not */
ZEND_METHOD(reflection_function,isDisabled)1719 ZEND_METHOD(reflection_function, isDisabled)
1720 {
1721 reflection_object *intern;
1722 zend_function *fptr;
1723
1724 GET_REFLECTION_OBJECT_PTR(fptr);
1725 RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
1726 }
1727 /* }}} */
1728
1729 /* {{{ proto public string ReflectionFunction::getFileName()
1730 Returns the filename of the file this function was declared in */
ZEND_METHOD(reflection_function,getFileName)1731 ZEND_METHOD(reflection_function, getFileName)
1732 {
1733 reflection_object *intern;
1734 zend_function *fptr;
1735
1736 if (zend_parse_parameters_none() == FAILURE) {
1737 return;
1738 }
1739 GET_REFLECTION_OBJECT_PTR(fptr);
1740 if (fptr->type == ZEND_USER_FUNCTION) {
1741 RETURN_STR_COPY(fptr->op_array.filename);
1742 }
1743 RETURN_FALSE;
1744 }
1745 /* }}} */
1746
1747 /* {{{ proto public int ReflectionFunction::getStartLine()
1748 Returns the line this function's declaration starts at */
ZEND_METHOD(reflection_function,getStartLine)1749 ZEND_METHOD(reflection_function, getStartLine)
1750 {
1751 reflection_object *intern;
1752 zend_function *fptr;
1753
1754 if (zend_parse_parameters_none() == FAILURE) {
1755 return;
1756 }
1757 GET_REFLECTION_OBJECT_PTR(fptr);
1758 if (fptr->type == ZEND_USER_FUNCTION) {
1759 RETURN_LONG(fptr->op_array.line_start);
1760 }
1761 RETURN_FALSE;
1762 }
1763 /* }}} */
1764
1765 /* {{{ proto public int ReflectionFunction::getEndLine()
1766 Returns the line this function's declaration ends at */
ZEND_METHOD(reflection_function,getEndLine)1767 ZEND_METHOD(reflection_function, getEndLine)
1768 {
1769 reflection_object *intern;
1770 zend_function *fptr;
1771
1772 if (zend_parse_parameters_none() == FAILURE) {
1773 return;
1774 }
1775 GET_REFLECTION_OBJECT_PTR(fptr);
1776 if (fptr->type == ZEND_USER_FUNCTION) {
1777 RETURN_LONG(fptr->op_array.line_end);
1778 }
1779 RETURN_FALSE;
1780 }
1781 /* }}} */
1782
1783 /* {{{ proto public string ReflectionFunction::getDocComment()
1784 Returns the doc comment for this function */
ZEND_METHOD(reflection_function,getDocComment)1785 ZEND_METHOD(reflection_function, getDocComment)
1786 {
1787 reflection_object *intern;
1788 zend_function *fptr;
1789
1790 if (zend_parse_parameters_none() == FAILURE) {
1791 return;
1792 }
1793 GET_REFLECTION_OBJECT_PTR(fptr);
1794 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
1795 RETURN_STR_COPY(fptr->op_array.doc_comment);
1796 }
1797 RETURN_FALSE;
1798 }
1799 /* }}} */
1800
1801 /* {{{ proto public array ReflectionFunction::getStaticVariables()
1802 Returns an associative array containing this function's static variables and their values */
ZEND_METHOD(reflection_function,getStaticVariables)1803 ZEND_METHOD(reflection_function, getStaticVariables)
1804 {
1805 reflection_object *intern;
1806 zend_function *fptr;
1807 zval *val;
1808
1809 if (zend_parse_parameters_none() == FAILURE) {
1810 return;
1811 }
1812 GET_REFLECTION_OBJECT_PTR(fptr);
1813
1814 /* Return an empty array in case no static variables exist */
1815 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
1816 array_init(return_value);
1817 if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
1818 if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
1819 GC_DELREF(fptr->op_array.static_variables);
1820 }
1821 fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
1822 }
1823 ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) {
1824 if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
1825 return;
1826 }
1827 } ZEND_HASH_FOREACH_END();
1828 zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref);
1829 } else {
1830 ZVAL_EMPTY_ARRAY(return_value);
1831 }
1832 }
1833 /* }}} */
1834
1835 /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
1836 Invokes the function */
ZEND_METHOD(reflection_function,invoke)1837 ZEND_METHOD(reflection_function, invoke)
1838 {
1839 zval retval;
1840 zval *params = NULL;
1841 int result, num_args = 0;
1842 zend_fcall_info fci;
1843 zend_fcall_info_cache fcc;
1844 reflection_object *intern;
1845 zend_function *fptr;
1846
1847 GET_REFLECTION_OBJECT_PTR(fptr);
1848
1849 if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", ¶ms, &num_args) == FAILURE) {
1850 return;
1851 }
1852
1853 fci.size = sizeof(fci);
1854 ZVAL_UNDEF(&fci.function_name);
1855 fci.object = NULL;
1856 fci.retval = &retval;
1857 fci.param_count = num_args;
1858 fci.params = params;
1859 fci.no_separation = 1;
1860
1861 fcc.function_handler = fptr;
1862 fcc.called_scope = NULL;
1863 fcc.object = NULL;
1864
1865 if (!Z_ISUNDEF(intern->obj)) {
1866 Z_OBJ_HT(intern->obj)->get_closure(
1867 &intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1868 }
1869
1870 result = zend_call_function(&fci, &fcc);
1871
1872 if (result == FAILURE) {
1873 zend_throw_exception_ex(reflection_exception_ptr, 0,
1874 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1875 return;
1876 }
1877
1878 if (Z_TYPE(retval) != IS_UNDEF) {
1879 if (Z_ISREF(retval)) {
1880 zend_unwrap_reference(&retval);
1881 }
1882 ZVAL_COPY_VALUE(return_value, &retval);
1883 }
1884 }
1885 /* }}} */
1886
1887 /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
1888 Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_function,invokeArgs)1889 ZEND_METHOD(reflection_function, invokeArgs)
1890 {
1891 zval retval;
1892 zval *params, *val;
1893 int result;
1894 int i, argc;
1895 zend_fcall_info fci;
1896 zend_fcall_info_cache fcc;
1897 reflection_object *intern;
1898 zend_function *fptr;
1899 zval *param_array;
1900
1901 GET_REFLECTION_OBJECT_PTR(fptr);
1902
1903 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", ¶m_array) == FAILURE) {
1904 return;
1905 }
1906
1907 argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
1908
1909 params = safe_emalloc(sizeof(zval), argc, 0);
1910 argc = 0;
1911 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
1912 ZVAL_COPY(¶ms[argc], val);
1913 argc++;
1914 } ZEND_HASH_FOREACH_END();
1915
1916 fci.size = sizeof(fci);
1917 ZVAL_UNDEF(&fci.function_name);
1918 fci.object = NULL;
1919 fci.retval = &retval;
1920 fci.param_count = argc;
1921 fci.params = params;
1922 fci.no_separation = 1;
1923
1924 fcc.function_handler = fptr;
1925 fcc.called_scope = NULL;
1926 fcc.object = NULL;
1927
1928 if (!Z_ISUNDEF(intern->obj)) {
1929 Z_OBJ_HT(intern->obj)->get_closure(
1930 &intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1931 }
1932
1933 result = zend_call_function(&fci, &fcc);
1934
1935 for (i = 0; i < argc; i++) {
1936 zval_ptr_dtor(¶ms[i]);
1937 }
1938 efree(params);
1939
1940 if (result == FAILURE) {
1941 zend_throw_exception_ex(reflection_exception_ptr, 0,
1942 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1943 return;
1944 }
1945
1946 if (Z_TYPE(retval) != IS_UNDEF) {
1947 if (Z_ISREF(retval)) {
1948 zend_unwrap_reference(&retval);
1949 }
1950 ZVAL_COPY_VALUE(return_value, &retval);
1951 }
1952 }
1953 /* }}} */
1954
1955 /* {{{ proto public bool ReflectionFunction::returnsReference()
1956 Gets whether this function returns a reference */
ZEND_METHOD(reflection_function,returnsReference)1957 ZEND_METHOD(reflection_function, returnsReference)
1958 {
1959 reflection_object *intern;
1960 zend_function *fptr;
1961
1962 GET_REFLECTION_OBJECT_PTR(fptr);
1963
1964 RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
1965 }
1966 /* }}} */
1967
1968 /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
1969 Gets the number of parameters */
ZEND_METHOD(reflection_function,getNumberOfParameters)1970 ZEND_METHOD(reflection_function, getNumberOfParameters)
1971 {
1972 reflection_object *intern;
1973 zend_function *fptr;
1974 uint32_t num_args;
1975
1976 GET_REFLECTION_OBJECT_PTR(fptr);
1977
1978 num_args = fptr->common.num_args;
1979 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
1980 num_args++;
1981 }
1982
1983 RETURN_LONG(num_args);
1984 }
1985 /* }}} */
1986
1987 /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
1988 Gets the number of required parameters */
ZEND_METHOD(reflection_function,getNumberOfRequiredParameters)1989 ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
1990 {
1991 reflection_object *intern;
1992 zend_function *fptr;
1993
1994 GET_REFLECTION_OBJECT_PTR(fptr);
1995
1996 RETURN_LONG(fptr->common.required_num_args);
1997 }
1998 /* }}} */
1999
2000 /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
2001 Returns an array of parameter objects for this function */
ZEND_METHOD(reflection_function,getParameters)2002 ZEND_METHOD(reflection_function, getParameters)
2003 {
2004 reflection_object *intern;
2005 zend_function *fptr;
2006 uint32_t i, num_args;
2007 struct _zend_arg_info *arg_info;
2008
2009 GET_REFLECTION_OBJECT_PTR(fptr);
2010
2011 arg_info= fptr->common.arg_info;
2012 num_args = fptr->common.num_args;
2013 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2014 num_args++;
2015 }
2016
2017 if (!num_args) {
2018 ZVAL_EMPTY_ARRAY(return_value);
2019 return;
2020 }
2021
2022 array_init(return_value);
2023 for (i = 0; i < num_args; i++) {
2024 zval parameter;
2025
2026 reflection_parameter_factory(
2027 _copy_function(fptr),
2028 Z_ISUNDEF(intern->obj) ? NULL : &intern->obj,
2029 arg_info,
2030 i,
2031 i < fptr->common.required_num_args,
2032 ¶meter
2033 );
2034 add_next_index_zval(return_value, ¶meter);
2035
2036 arg_info++;
2037 }
2038 }
2039 /* }}} */
2040
2041 /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
2042 Returns NULL or the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtension)2043 ZEND_METHOD(reflection_function, getExtension)
2044 {
2045 reflection_object *intern;
2046 zend_function *fptr;
2047 zend_internal_function *internal;
2048
2049 GET_REFLECTION_OBJECT_PTR(fptr);
2050
2051 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2052 RETURN_NULL();
2053 }
2054
2055 internal = (zend_internal_function *)fptr;
2056 if (internal->module) {
2057 reflection_extension_factory(return_value, internal->module->name);
2058 } else {
2059 RETURN_NULL();
2060 }
2061 }
2062 /* }}} */
2063
2064 /* {{{ proto public string|false ReflectionFunction::getExtensionName()
2065 Returns false or the name of the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtensionName)2066 ZEND_METHOD(reflection_function, getExtensionName)
2067 {
2068 reflection_object *intern;
2069 zend_function *fptr;
2070 zend_internal_function *internal;
2071
2072 GET_REFLECTION_OBJECT_PTR(fptr);
2073
2074 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2075 RETURN_FALSE;
2076 }
2077
2078 internal = (zend_internal_function *)fptr;
2079 if (internal->module) {
2080 RETURN_STRING(internal->module->name);
2081 } else {
2082 RETURN_FALSE;
2083 }
2084 }
2085 /* }}} */
2086
2087 /* {{{ proto public void ReflectionGenerator::__construct(object Generator) */
ZEND_METHOD(reflection_generator,__construct)2088 ZEND_METHOD(reflection_generator, __construct)
2089 {
2090 zval *generator, *object;
2091 reflection_object *intern;
2092 zend_execute_data *ex;
2093
2094 object = getThis();
2095 intern = Z_REFLECTION_P(object);
2096
2097 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &generator, zend_ce_generator) == FAILURE) {
2098 return;
2099 }
2100
2101 ex = ((zend_generator *) Z_OBJ_P(generator))->execute_data;
2102 if (!ex) {
2103 _DO_THROW("Cannot create ReflectionGenerator based on a terminated Generator");
2104 return;
2105 }
2106
2107 intern->ref_type = REF_TYPE_GENERATOR;
2108 ZVAL_COPY(&intern->obj, generator);
2109 intern->ce = zend_ce_generator;
2110 }
2111 /* }}} */
2112
2113 #define REFLECTION_CHECK_VALID_GENERATOR(ex) \
2114 if (!ex) { \
2115 _DO_THROW("Cannot fetch information from a terminated Generator"); \
2116 return; \
2117 }
2118
2119 /* {{{ proto public array ReflectionGenerator::getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT) */
ZEND_METHOD(reflection_generator,getTrace)2120 ZEND_METHOD(reflection_generator, getTrace)
2121 {
2122 zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2123 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2124 zend_generator *root_generator;
2125 zend_execute_data *ex_backup = EG(current_execute_data);
2126 zend_execute_data *ex = generator->execute_data;
2127 zend_execute_data *root_prev = NULL, *cur_prev;
2128
2129 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &options) == FAILURE) {
2130 return;
2131 }
2132
2133 REFLECTION_CHECK_VALID_GENERATOR(ex)
2134
2135 root_generator = zend_generator_get_current(generator);
2136
2137 cur_prev = generator->execute_data->prev_execute_data;
2138 if (generator == root_generator) {
2139 generator->execute_data->prev_execute_data = NULL;
2140 } else {
2141 root_prev = root_generator->execute_data->prev_execute_data;
2142 generator->execute_fake.prev_execute_data = NULL;
2143 root_generator->execute_data->prev_execute_data = &generator->execute_fake;
2144 }
2145
2146 EG(current_execute_data) = root_generator->execute_data;
2147 zend_fetch_debug_backtrace(return_value, 0, options, 0);
2148 EG(current_execute_data) = ex_backup;
2149
2150 root_generator->execute_data->prev_execute_data = root_prev;
2151 generator->execute_data->prev_execute_data = cur_prev;
2152 }
2153 /* }}} */
2154
2155 /* {{{ proto public int ReflectionGenerator::getExecutingLine() */
ZEND_METHOD(reflection_generator,getExecutingLine)2156 ZEND_METHOD(reflection_generator, getExecutingLine)
2157 {
2158 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2159 zend_execute_data *ex = generator->execute_data;
2160
2161 if (zend_parse_parameters_none() == FAILURE) {
2162 return;
2163 }
2164
2165 REFLECTION_CHECK_VALID_GENERATOR(ex)
2166
2167 ZVAL_LONG(return_value, ex->opline->lineno);
2168 }
2169 /* }}} */
2170
2171 /* {{{ proto public string ReflectionGenerator::getExecutingFile() */
ZEND_METHOD(reflection_generator,getExecutingFile)2172 ZEND_METHOD(reflection_generator, getExecutingFile)
2173 {
2174 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2175 zend_execute_data *ex = generator->execute_data;
2176
2177 if (zend_parse_parameters_none() == FAILURE) {
2178 return;
2179 }
2180
2181 REFLECTION_CHECK_VALID_GENERATOR(ex)
2182
2183 ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
2184 }
2185 /* }}} */
2186
2187 /* {{{ proto public ReflectionFunctionAbstract ReflectionGenerator::getFunction() */
ZEND_METHOD(reflection_generator,getFunction)2188 ZEND_METHOD(reflection_generator, getFunction)
2189 {
2190 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2191 zend_execute_data *ex = generator->execute_data;
2192
2193 if (zend_parse_parameters_none() == FAILURE) {
2194 return;
2195 }
2196
2197 REFLECTION_CHECK_VALID_GENERATOR(ex)
2198
2199 if (ex->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2200 zval closure;
2201 ZVAL_OBJ(&closure, ZEND_CLOSURE_OBJECT(ex->func));
2202 reflection_function_factory(ex->func, &closure, return_value);
2203 } else if (ex->func->op_array.scope) {
2204 reflection_method_factory(ex->func->op_array.scope, ex->func, NULL, return_value);
2205 } else {
2206 reflection_function_factory(ex->func, NULL, return_value);
2207 }
2208 }
2209 /* }}} */
2210
2211 /* {{{ proto public object ReflectionGenerator::getThis() */
ZEND_METHOD(reflection_generator,getThis)2212 ZEND_METHOD(reflection_generator, getThis)
2213 {
2214 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2215 zend_execute_data *ex = generator->execute_data;
2216
2217 if (zend_parse_parameters_none() == FAILURE) {
2218 return;
2219 }
2220
2221 REFLECTION_CHECK_VALID_GENERATOR(ex)
2222
2223 if (Z_TYPE(ex->This) == IS_OBJECT) {
2224 ZVAL_COPY(return_value, &ex->This);
2225 } else {
2226 ZVAL_NULL(return_value);
2227 }
2228 }
2229 /* }}} */
2230
2231 /* {{{ proto public Generator ReflectionGenerator::getExecutingGenerator() */
ZEND_METHOD(reflection_generator,getExecutingGenerator)2232 ZEND_METHOD(reflection_generator, getExecutingGenerator)
2233 {
2234 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2235 zend_execute_data *ex = generator->execute_data;
2236 zend_generator *current;
2237
2238 if (zend_parse_parameters_none() == FAILURE) {
2239 return;
2240 }
2241
2242 REFLECTION_CHECK_VALID_GENERATOR(ex)
2243
2244 current = zend_generator_get_current(generator);
2245 GC_ADDREF(¤t->std);
2246
2247 ZVAL_OBJ(return_value, (zend_object *) current);
2248 }
2249 /* }}} */
2250
2251 /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
2252 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_parameter,export)2253 ZEND_METHOD(reflection_parameter, export)
2254 {
2255 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
2256 }
2257 /* }}} */
2258
2259 /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
2260 Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_parameter,__construct)2261 ZEND_METHOD(reflection_parameter, __construct)
2262 {
2263 parameter_reference *ref;
2264 zval *reference, *parameter;
2265 zval *object;
2266 zval name;
2267 reflection_object *intern;
2268 zend_function *fptr;
2269 struct _zend_arg_info *arg_info;
2270 int position;
2271 uint32_t num_args;
2272 zend_class_entry *ce = NULL;
2273 zend_bool is_closure = 0;
2274
2275 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zz", &reference, ¶meter) == FAILURE) {
2276 return;
2277 }
2278
2279 object = getThis();
2280 intern = Z_REFLECTION_P(object);
2281
2282 /* First, find the function */
2283 switch (Z_TYPE_P(reference)) {
2284 case IS_STRING: {
2285 size_t lcname_len;
2286 char *lcname;
2287
2288 lcname_len = Z_STRLEN_P(reference);
2289 lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
2290 if ((fptr = zend_hash_str_find_ptr(EG(function_table), lcname, lcname_len)) == NULL) {
2291 efree(lcname);
2292 zend_throw_exception_ex(reflection_exception_ptr, 0,
2293 "Function %s() does not exist", Z_STRVAL_P(reference));
2294 return;
2295 }
2296 efree(lcname);
2297 }
2298 ce = fptr->common.scope;
2299 break;
2300
2301 case IS_ARRAY: {
2302 zval *classref;
2303 zval *method;
2304 size_t lcname_len;
2305 char *lcname;
2306
2307 if (((classref =zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
2308 || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
2309 {
2310 _DO_THROW("Expected array($object, $method) or array($classname, $method)");
2311 /* returns out of this function */
2312 }
2313
2314 if (Z_TYPE_P(classref) == IS_OBJECT) {
2315 ce = Z_OBJCE_P(classref);
2316 } else {
2317 convert_to_string_ex(classref);
2318 if ((ce = zend_lookup_class(Z_STR_P(classref))) == NULL) {
2319 zend_throw_exception_ex(reflection_exception_ptr, 0,
2320 "Class %s does not exist", Z_STRVAL_P(classref));
2321 return;
2322 }
2323 }
2324
2325 convert_to_string_ex(method);
2326 lcname_len = Z_STRLEN_P(method);
2327 lcname = zend_str_tolower_dup(Z_STRVAL_P(method), lcname_len);
2328 if (ce == zend_ce_closure && Z_TYPE_P(classref) == IS_OBJECT
2329 && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
2330 && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
2331 && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
2332 {
2333 /* nothing to do. don't set is_closure since is the invoke handler,
2334 not the closure itself */
2335 } else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, lcname, lcname_len)) == NULL) {
2336 efree(lcname);
2337 zend_throw_exception_ex(reflection_exception_ptr, 0,
2338 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), Z_STRVAL_P(method));
2339 return;
2340 }
2341 efree(lcname);
2342 }
2343 break;
2344
2345 case IS_OBJECT: {
2346 ce = Z_OBJCE_P(reference);
2347
2348 if (instanceof_function(ce, zend_ce_closure)) {
2349 fptr = (zend_function *)zend_get_closure_method_def(reference);
2350 Z_ADDREF_P(reference);
2351 is_closure = 1;
2352 } else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME))) == NULL) {
2353 zend_throw_exception_ex(reflection_exception_ptr, 0,
2354 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
2355 return;
2356 }
2357 }
2358 break;
2359
2360 default:
2361 _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
2362 /* returns out of this function */
2363 }
2364
2365 /* Now, search for the parameter */
2366 arg_info = fptr->common.arg_info;
2367 num_args = fptr->common.num_args;
2368 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2369 num_args++;
2370 }
2371 if (Z_TYPE_P(parameter) == IS_LONG) {
2372 position= (int)Z_LVAL_P(parameter);
2373 if (position < 0 || (uint32_t)position >= num_args) {
2374 if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2375 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2376 zend_string_release_ex(fptr->common.function_name, 0);
2377 }
2378 zend_free_trampoline(fptr);
2379 }
2380 if (is_closure) {
2381 zval_ptr_dtor(reference);
2382 }
2383 _DO_THROW("The parameter specified by its offset could not be found");
2384 /* returns out of this function */
2385 }
2386 } else {
2387 uint32_t i;
2388
2389 position= -1;
2390 convert_to_string_ex(parameter);
2391 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2392 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2393 for (i = 0; i < num_args; i++) {
2394 if (arg_info[i].name) {
2395 if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
2396 position= i;
2397 break;
2398 }
2399
2400 }
2401 }
2402 } else {
2403 for (i = 0; i < num_args; i++) {
2404 if (arg_info[i].name) {
2405 if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) {
2406 position= i;
2407 break;
2408 }
2409 }
2410 }
2411 }
2412 if (position == -1) {
2413 if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2414 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2415 zend_string_release_ex(fptr->common.function_name, 0);
2416 }
2417 zend_free_trampoline(fptr);
2418 }
2419 if (is_closure) {
2420 zval_ptr_dtor(reference);
2421 }
2422 _DO_THROW("The parameter specified by its name could not be found");
2423 /* returns out of this function */
2424 }
2425 }
2426
2427 if (arg_info[position].name) {
2428 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2429 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2430 ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)[position].name);
2431 } else {
2432 ZVAL_STR_COPY(&name, arg_info[position].name);
2433 }
2434 } else {
2435 ZVAL_NULL(&name);
2436 }
2437 reflection_update_property_name(object, &name);
2438
2439 ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
2440 ref->arg_info = &arg_info[position];
2441 ref->offset = (uint32_t)position;
2442 ref->required = position < fptr->common.required_num_args;
2443 ref->fptr = fptr;
2444 /* TODO: copy fptr */
2445 intern->ptr = ref;
2446 intern->ref_type = REF_TYPE_PARAMETER;
2447 intern->ce = ce;
2448 if (reference && is_closure) {
2449 ZVAL_COPY_VALUE(&intern->obj, reference);
2450 }
2451 }
2452 /* }}} */
2453
2454 /* {{{ proto public string ReflectionParameter::__toString()
2455 Returns a string representation */
ZEND_METHOD(reflection_parameter,__toString)2456 ZEND_METHOD(reflection_parameter, __toString)
2457 {
2458 reflection_object *intern;
2459 parameter_reference *param;
2460 smart_str str = {0};
2461
2462 if (zend_parse_parameters_none() == FAILURE) {
2463 return;
2464 }
2465 GET_REFLECTION_OBJECT_PTR(param);
2466 _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
2467 RETURN_STR(smart_str_extract(&str));
2468 }
2469
2470 /* }}} */
2471
2472 /* {{{ proto public string ReflectionParameter::getName()
2473 Returns this parameters's name */
ZEND_METHOD(reflection_parameter,getName)2474 ZEND_METHOD(reflection_parameter, getName)
2475 {
2476 if (zend_parse_parameters_none() == FAILURE) {
2477 return;
2478 }
2479 _default_get_name(getThis(), return_value);
2480 }
2481 /* }}} */
2482
2483 /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
2484 Returns the ReflectionFunction for the function of this parameter */
ZEND_METHOD(reflection_parameter,getDeclaringFunction)2485 ZEND_METHOD(reflection_parameter, getDeclaringFunction)
2486 {
2487 reflection_object *intern;
2488 parameter_reference *param;
2489
2490 if (zend_parse_parameters_none() == FAILURE) {
2491 return;
2492 }
2493 GET_REFLECTION_OBJECT_PTR(param);
2494
2495 if (!param->fptr->common.scope) {
2496 reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2497 } else {
2498 reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2499 }
2500 }
2501 /* }}} */
2502
2503 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
2504 Returns in which class this parameter is defined (not the type of the parameter) */
ZEND_METHOD(reflection_parameter,getDeclaringClass)2505 ZEND_METHOD(reflection_parameter, getDeclaringClass)
2506 {
2507 reflection_object *intern;
2508 parameter_reference *param;
2509
2510 if (zend_parse_parameters_none() == FAILURE) {
2511 return;
2512 }
2513 GET_REFLECTION_OBJECT_PTR(param);
2514
2515 if (param->fptr->common.scope) {
2516 zend_reflection_class_factory(param->fptr->common.scope, return_value);
2517 }
2518 }
2519 /* }}} */
2520
2521 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
2522 Returns this parameters's class hint or NULL if there is none */
ZEND_METHOD(reflection_parameter,getClass)2523 ZEND_METHOD(reflection_parameter, getClass)
2524 {
2525 reflection_object *intern;
2526 parameter_reference *param;
2527 zend_class_entry *ce;
2528
2529 if (zend_parse_parameters_none() == FAILURE) {
2530 return;
2531 }
2532 GET_REFLECTION_OBJECT_PTR(param);
2533
2534 if (ZEND_TYPE_IS_CLASS(param->arg_info->type)) {
2535 /* Class name is stored as a string, we might also get "self" or "parent"
2536 * - For "self", simply use the function scope. If scope is NULL then
2537 * the function is global and thus self does not make any sense
2538 *
2539 * - For "parent", use the function scope's parent. If scope is NULL then
2540 * the function is global and thus parent does not make any sense.
2541 * If the parent is NULL then the class does not extend anything and
2542 * thus parent does not make any sense, either.
2543 *
2544 * TODO: Think about moving these checks to the compiler or some sort of
2545 * lint-mode.
2546 */
2547 zend_string *class_name;
2548
2549 class_name = ZEND_TYPE_NAME(param->arg_info->type);
2550 if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "self", sizeof("self")- 1)) {
2551 ce = param->fptr->common.scope;
2552 if (!ce) {
2553 zend_throw_exception_ex(reflection_exception_ptr, 0,
2554 "Parameter uses 'self' as type hint but function is not a class member!");
2555 return;
2556 }
2557 } else if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "parent", sizeof("parent")- 1)) {
2558 ce = param->fptr->common.scope;
2559 if (!ce) {
2560 zend_throw_exception_ex(reflection_exception_ptr, 0,
2561 "Parameter uses 'parent' as type hint but function is not a class member!");
2562 return;
2563 }
2564 if (!ce->parent) {
2565 zend_throw_exception_ex(reflection_exception_ptr, 0,
2566 "Parameter uses 'parent' as type hint although class does not have a parent!");
2567 return;
2568 }
2569 ce = ce->parent;
2570 } else {
2571 ce = zend_lookup_class(class_name);
2572 if (!ce) {
2573 zend_throw_exception_ex(reflection_exception_ptr, 0,
2574 "Class %s does not exist", ZSTR_VAL(class_name));
2575 return;
2576 }
2577 }
2578 zend_reflection_class_factory(ce, return_value);
2579 }
2580 }
2581 /* }}} */
2582
2583 /* {{{ proto public bool ReflectionParameter::hasType()
2584 Returns whether parameter has a type */
ZEND_METHOD(reflection_parameter,hasType)2585 ZEND_METHOD(reflection_parameter, hasType)
2586 {
2587 reflection_object *intern;
2588 parameter_reference *param;
2589
2590 if (zend_parse_parameters_none() == FAILURE) {
2591 return;
2592 }
2593 GET_REFLECTION_OBJECT_PTR(param);
2594
2595 RETVAL_BOOL(ZEND_TYPE_IS_SET(param->arg_info->type));
2596 }
2597 /* }}} */
2598
2599 /* {{{ proto public ReflectionType ReflectionParameter::getType()
2600 Returns the type associated with the parameter */
ZEND_METHOD(reflection_parameter,getType)2601 ZEND_METHOD(reflection_parameter, getType)
2602 {
2603 reflection_object *intern;
2604 parameter_reference *param;
2605
2606 if (zend_parse_parameters_none() == FAILURE) {
2607 return;
2608 }
2609 GET_REFLECTION_OBJECT_PTR(param);
2610
2611 if (!ZEND_TYPE_IS_SET(param->arg_info->type)) {
2612 RETURN_NULL();
2613 }
2614 reflection_type_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, param->arg_info, return_value);
2615 }
2616 /* }}} */
2617
2618 /* {{{ proto public bool ReflectionParameter::isArray()
2619 Returns whether parameter MUST be an array */
ZEND_METHOD(reflection_parameter,isArray)2620 ZEND_METHOD(reflection_parameter, isArray)
2621 {
2622 reflection_object *intern;
2623 parameter_reference *param;
2624
2625 if (zend_parse_parameters_none() == FAILURE) {
2626 return;
2627 }
2628 GET_REFLECTION_OBJECT_PTR(param);
2629
2630 RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_ARRAY);
2631 }
2632 /* }}} */
2633
2634 /* {{{ proto public bool ReflectionParameter::isCallable()
2635 Returns whether parameter MUST be callable */
ZEND_METHOD(reflection_parameter,isCallable)2636 ZEND_METHOD(reflection_parameter, isCallable)
2637 {
2638 reflection_object *intern;
2639 parameter_reference *param;
2640
2641 if (zend_parse_parameters_none() == FAILURE) {
2642 return;
2643 }
2644 GET_REFLECTION_OBJECT_PTR(param);
2645
2646 RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_CALLABLE);
2647 }
2648 /* }}} */
2649
2650 /* {{{ proto public bool ReflectionParameter::allowsNull()
2651 Returns whether NULL is allowed as this parameters's value */
ZEND_METHOD(reflection_parameter,allowsNull)2652 ZEND_METHOD(reflection_parameter, allowsNull)
2653 {
2654 reflection_object *intern;
2655 parameter_reference *param;
2656
2657 if (zend_parse_parameters_none() == FAILURE) {
2658 return;
2659 }
2660 GET_REFLECTION_OBJECT_PTR(param);
2661
2662 RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
2663 }
2664 /* }}} */
2665
2666 /* {{{ proto public bool ReflectionParameter::isPassedByReference()
2667 Returns whether this parameters is passed to by reference */
ZEND_METHOD(reflection_parameter,isPassedByReference)2668 ZEND_METHOD(reflection_parameter, isPassedByReference)
2669 {
2670 reflection_object *intern;
2671 parameter_reference *param;
2672
2673 if (zend_parse_parameters_none() == FAILURE) {
2674 return;
2675 }
2676 GET_REFLECTION_OBJECT_PTR(param);
2677
2678 RETVAL_BOOL(param->arg_info->pass_by_reference);
2679 }
2680 /* }}} */
2681
2682 /* {{{ proto public bool ReflectionParameter::canBePassedByValue()
2683 Returns whether this parameter can be passed by value */
ZEND_METHOD(reflection_parameter,canBePassedByValue)2684 ZEND_METHOD(reflection_parameter, canBePassedByValue)
2685 {
2686 reflection_object *intern;
2687 parameter_reference *param;
2688
2689 if (zend_parse_parameters_none() == FAILURE) {
2690 return;
2691 }
2692 GET_REFLECTION_OBJECT_PTR(param);
2693
2694 /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
2695 RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
2696 }
2697 /* }}} */
2698
2699 /* {{{ proto public bool ReflectionParameter::getPosition()
2700 Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,getPosition)2701 ZEND_METHOD(reflection_parameter, getPosition)
2702 {
2703 reflection_object *intern;
2704 parameter_reference *param;
2705
2706 if (zend_parse_parameters_none() == FAILURE) {
2707 return;
2708 }
2709 GET_REFLECTION_OBJECT_PTR(param);
2710
2711 RETVAL_LONG(param->offset);
2712 }
2713 /* }}} */
2714
2715 /* {{{ proto public bool ReflectionParameter::isOptional()
2716 Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,isOptional)2717 ZEND_METHOD(reflection_parameter, isOptional)
2718 {
2719 reflection_object *intern;
2720 parameter_reference *param;
2721
2722 if (zend_parse_parameters_none() == FAILURE) {
2723 return;
2724 }
2725 GET_REFLECTION_OBJECT_PTR(param);
2726
2727 RETVAL_BOOL(!param->required);
2728 }
2729 /* }}} */
2730
2731 /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
2732 Returns whether the default value of this parameter is available */
ZEND_METHOD(reflection_parameter,isDefaultValueAvailable)2733 ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2734 {
2735 reflection_object *intern;
2736 parameter_reference *param;
2737 zend_op *precv;
2738
2739 if (zend_parse_parameters_none() == FAILURE) {
2740 return;
2741 }
2742 GET_REFLECTION_OBJECT_PTR(param);
2743
2744 if (param->fptr->type != ZEND_USER_FUNCTION)
2745 {
2746 RETURN_FALSE;
2747 }
2748
2749 precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
2750 if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
2751 RETURN_FALSE;
2752 }
2753 RETURN_TRUE;
2754 }
2755 /* }}} */
2756
2757 /* {{{ proto public bool ReflectionParameter::getDefaultValue()
2758 Returns the default value of this parameter or throws an exception */
ZEND_METHOD(reflection_parameter,getDefaultValue)2759 ZEND_METHOD(reflection_parameter, getDefaultValue)
2760 {
2761 parameter_reference *param;
2762 zend_op *precv;
2763
2764 if (zend_parse_parameters_none() == FAILURE) {
2765 return;
2766 }
2767
2768 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2769 if (!param) {
2770 return;
2771 }
2772
2773 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2774 if (!precv) {
2775 return;
2776 }
2777
2778 ZVAL_COPY(return_value, RT_CONSTANT(precv, precv->op2));
2779 if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
2780 zval_update_constant_ex(return_value, param->fptr->common.scope);
2781 }
2782 }
2783 /* }}} */
2784
2785 /* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
2786 Returns whether the default value of this parameter is constant */
ZEND_METHOD(reflection_parameter,isDefaultValueConstant)2787 ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2788 {
2789 zend_op *precv;
2790 parameter_reference *param;
2791
2792 if (zend_parse_parameters_none() == FAILURE) {
2793 return;
2794 }
2795
2796 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2797 if (!param) {
2798 RETURN_FALSE;
2799 }
2800
2801 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2802 if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2803 zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2804
2805 if (ast->kind == ZEND_AST_CONSTANT
2806 || ast->kind == ZEND_AST_CONSTANT_CLASS) {
2807 RETURN_TRUE;
2808 }
2809 }
2810
2811 RETURN_FALSE;
2812 }
2813 /* }}} */
2814
2815 /* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
2816 Returns the default value's constant name if default value is constant or null */
ZEND_METHOD(reflection_parameter,getDefaultValueConstantName)2817 ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
2818 {
2819 zend_op *precv;
2820 parameter_reference *param;
2821
2822 if (zend_parse_parameters_none() == FAILURE) {
2823 return;
2824 }
2825
2826 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2827 if (!param) {
2828 return;
2829 }
2830
2831 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2832 if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2833 zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2834
2835 if (ast->kind == ZEND_AST_CONSTANT) {
2836 RETURN_STR_COPY(zend_ast_get_constant_name(ast));
2837 } else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
2838 RETURN_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
2839 }
2840 }
2841 }
2842 /* }}} */
2843
2844 /* {{{ proto public bool ReflectionParameter::isVariadic()
2845 Returns whether this parameter is a variadic parameter */
ZEND_METHOD(reflection_parameter,isVariadic)2846 ZEND_METHOD(reflection_parameter, isVariadic)
2847 {
2848 reflection_object *intern;
2849 parameter_reference *param;
2850
2851 if (zend_parse_parameters_none() == FAILURE) {
2852 return;
2853 }
2854 GET_REFLECTION_OBJECT_PTR(param);
2855
2856 RETVAL_BOOL(param->arg_info->is_variadic);
2857 }
2858 /* }}} */
2859
2860 /* {{{ proto public bool ReflectionType::allowsNull()
2861 Returns whether parameter MAY be null */
ZEND_METHOD(reflection_type,allowsNull)2862 ZEND_METHOD(reflection_type, allowsNull)
2863 {
2864 reflection_object *intern;
2865 type_reference *param;
2866
2867 if (zend_parse_parameters_none() == FAILURE) {
2868 return;
2869 }
2870 GET_REFLECTION_OBJECT_PTR(param);
2871
2872 RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
2873 }
2874 /* }}} */
2875
2876 /* {{{ proto public bool ReflectionType::isBuiltin()
2877 Returns whether parameter is a builtin type */
ZEND_METHOD(reflection_type,isBuiltin)2878 ZEND_METHOD(reflection_type, isBuiltin)
2879 {
2880 reflection_object *intern;
2881 type_reference *param;
2882
2883 if (zend_parse_parameters_none() == FAILURE) {
2884 return;
2885 }
2886 GET_REFLECTION_OBJECT_PTR(param);
2887
2888 RETVAL_BOOL(ZEND_TYPE_IS_CODE(param->arg_info->type));
2889 }
2890 /* }}} */
2891
2892 /* {{{ reflection_type_name */
reflection_type_name(type_reference * param)2893 static zend_string *reflection_type_name(type_reference *param) {
2894 if (ZEND_TYPE_IS_CLASS(param->arg_info->type)) {
2895 return zend_string_copy(ZEND_TYPE_NAME(param->arg_info->type));
2896 } else {
2897 char *name = zend_get_type_by_const(ZEND_TYPE_CODE(param->arg_info->type));
2898 return zend_string_init(name, strlen(name), 0);
2899 }
2900 }
2901 /* }}} */
2902
2903 /* {{{ proto public string ReflectionType::__toString()
2904 Return the text of the type hint */
ZEND_METHOD(reflection_type,__toString)2905 ZEND_METHOD(reflection_type, __toString)
2906 {
2907 reflection_object *intern;
2908 type_reference *param;
2909
2910 if (zend_parse_parameters_none() == FAILURE) {
2911 return;
2912 }
2913 GET_REFLECTION_OBJECT_PTR(param);
2914
2915 RETURN_STR(reflection_type_name(param));
2916 }
2917 /* }}} */
2918
2919 /* {{{ proto public string ReflectionNamedType::getName()
2920 Return the text of the type hint */
ZEND_METHOD(reflection_named_type,getName)2921 ZEND_METHOD(reflection_named_type, getName)
2922 {
2923 reflection_object *intern;
2924 type_reference *param;
2925
2926 if (zend_parse_parameters_none() == FAILURE) {
2927 return;
2928 }
2929 GET_REFLECTION_OBJECT_PTR(param);
2930
2931 RETURN_STR(reflection_type_name(param));
2932 }
2933 /* }}} */
2934
2935 /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
2936 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_method,export)2937 ZEND_METHOD(reflection_method, export)
2938 {
2939 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
2940 }
2941 /* }}} */
2942
2943 /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
2944 Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_method,__construct)2945 ZEND_METHOD(reflection_method, __construct)
2946 {
2947 zval name, *classname;
2948 zval *object, *orig_obj;
2949 reflection_object *intern;
2950 char *lcname;
2951 zend_class_entry *ce;
2952 zend_function *mptr;
2953 char *name_str, *tmp;
2954 size_t name_len, tmp_len;
2955 zval ztmp;
2956
2957 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
2958 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
2959 return;
2960 }
2961
2962 if ((tmp = strstr(name_str, "::")) == NULL) {
2963 zend_throw_exception_ex(reflection_exception_ptr, 0,
2964 "Invalid method name %s", name_str);
2965 return;
2966 }
2967 classname = &ztmp;
2968 tmp_len = tmp - name_str;
2969 ZVAL_STRINGL(classname, name_str, tmp_len);
2970 name_len = name_len - (tmp_len + 2);
2971 name_str = tmp + 2;
2972 orig_obj = NULL;
2973 } else if (Z_TYPE_P(classname) == IS_OBJECT) {
2974 orig_obj = classname;
2975 } else {
2976 orig_obj = NULL;
2977 }
2978
2979 object = getThis();
2980 intern = Z_REFLECTION_P(object);
2981
2982 /* Find the class entry */
2983 switch (Z_TYPE_P(classname)) {
2984 case IS_STRING:
2985 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
2986 if (!EG(exception)) {
2987 zend_throw_exception_ex(reflection_exception_ptr, 0,
2988 "Class %s does not exist", Z_STRVAL_P(classname));
2989 }
2990 if (classname == &ztmp) {
2991 zval_ptr_dtor_str(&ztmp);
2992 }
2993 return;
2994 }
2995 break;
2996
2997 case IS_OBJECT:
2998 ce = Z_OBJCE_P(classname);
2999 break;
3000
3001 default:
3002 if (classname == &ztmp) {
3003 zval_ptr_dtor_str(&ztmp);
3004 }
3005 _DO_THROW("The parameter class is expected to be either a string or an object");
3006 /* returns out of this function */
3007 }
3008
3009 if (classname == &ztmp) {
3010 zval_ptr_dtor_str(&ztmp);
3011 }
3012
3013 lcname = zend_str_tolower_dup(name_str, name_len);
3014
3015 if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
3016 && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
3017 && (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
3018 {
3019 /* do nothing, mptr already set */
3020 } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
3021 efree(lcname);
3022 zend_throw_exception_ex(reflection_exception_ptr, 0,
3023 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
3024 return;
3025 }
3026 efree(lcname);
3027
3028 ZVAL_STR_COPY(&name, mptr->common.scope->name);
3029 reflection_update_property_class(object, &name);
3030 ZVAL_STR_COPY(&name, mptr->common.function_name);
3031 reflection_update_property_name(object, &name);
3032 intern->ptr = mptr;
3033 intern->ref_type = REF_TYPE_FUNCTION;
3034 intern->ce = ce;
3035 }
3036 /* }}} */
3037
3038 /* {{{ proto public string ReflectionMethod::__toString()
3039 Returns a string representation */
ZEND_METHOD(reflection_method,__toString)3040 ZEND_METHOD(reflection_method, __toString)
3041 {
3042 reflection_object *intern;
3043 zend_function *mptr;
3044 smart_str str = {0};
3045
3046 if (zend_parse_parameters_none() == FAILURE) {
3047 return;
3048 }
3049 GET_REFLECTION_OBJECT_PTR(mptr);
3050 _function_string(&str, mptr, intern->ce, "");
3051 RETURN_STR(smart_str_extract(&str));
3052 }
3053 /* }}} */
3054
3055 /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
3056 Invokes the function */
ZEND_METHOD(reflection_method,getClosure)3057 ZEND_METHOD(reflection_method, getClosure)
3058 {
3059 reflection_object *intern;
3060 zval *obj;
3061 zend_function *mptr;
3062
3063 GET_REFLECTION_OBJECT_PTR(mptr);
3064
3065 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3066 zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
3067 } else {
3068 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
3069 return;
3070 }
3071
3072 if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
3073 _DO_THROW("Given object is not an instance of the class this method was declared in");
3074 /* Returns from this function */
3075 }
3076
3077 /* This is an original closure object and __invoke is to be called. */
3078 if (Z_OBJCE_P(obj) == zend_ce_closure &&
3079 (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
3080 {
3081 ZVAL_COPY(return_value, obj);
3082 } else {
3083 zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
3084 }
3085 }
3086 }
3087 /* }}} */
3088
3089 /* {{{ reflection_method_invoke */
reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS,int variadic)3090 static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
3091 {
3092 zval retval;
3093 zval *params = NULL, *val, *object;
3094 reflection_object *intern;
3095 zend_function *mptr;
3096 int i, argc = 0, result;
3097 zend_fcall_info fci;
3098 zend_fcall_info_cache fcc;
3099 zend_class_entry *obj_ce;
3100 zval *param_array;
3101
3102 GET_REFLECTION_OBJECT_PTR(mptr);
3103
3104 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3105 zend_throw_exception_ex(reflection_exception_ptr, 0,
3106 "Trying to invoke abstract method %s::%s()",
3107 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3108 return;
3109 }
3110
3111 if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
3112 zend_throw_exception_ex(reflection_exception_ptr, 0,
3113 "Trying to invoke %s method %s::%s() from scope %s",
3114 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
3115 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
3116 ZSTR_VAL(Z_OBJCE_P(getThis())->name));
3117 return;
3118 }
3119
3120 if (variadic) {
3121 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!*", &object, ¶ms, &argc) == FAILURE) {
3122 return;
3123 }
3124 } else {
3125 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, ¶m_array) == FAILURE) {
3126 return;
3127 }
3128
3129 argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
3130
3131 params = safe_emalloc(sizeof(zval), argc, 0);
3132 argc = 0;
3133 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
3134 ZVAL_COPY(¶ms[argc], val);
3135 argc++;
3136 } ZEND_HASH_FOREACH_END();
3137 }
3138
3139 /* In case this is a static method, we should'nt pass an object_ptr
3140 * (which is used as calling context aka $this). We can thus ignore the
3141 * first parameter.
3142 *
3143 * Else, we verify that the given object is an instance of the class.
3144 */
3145 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3146 object = NULL;
3147 obj_ce = mptr->common.scope;
3148 } else {
3149 if (!object) {
3150 zend_throw_exception_ex(reflection_exception_ptr, 0,
3151 "Trying to invoke non static method %s::%s() without an object",
3152 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3153 return;
3154 }
3155
3156 obj_ce = Z_OBJCE_P(object);
3157
3158 if (!instanceof_function(obj_ce, mptr->common.scope)) {
3159 if (!variadic) {
3160 efree(params);
3161 }
3162 _DO_THROW("Given object is not an instance of the class this method was declared in");
3163 /* Returns from this function */
3164 }
3165 }
3166
3167 fci.size = sizeof(fci);
3168 ZVAL_UNDEF(&fci.function_name);
3169 fci.object = object ? Z_OBJ_P(object) : NULL;
3170 fci.retval = &retval;
3171 fci.param_count = argc;
3172 fci.params = params;
3173 fci.no_separation = 1;
3174
3175 fcc.function_handler = mptr;
3176 fcc.called_scope = intern->ce;
3177 fcc.object = object ? Z_OBJ_P(object) : NULL;
3178
3179 /*
3180 * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
3181 */
3182 if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3183 fcc.function_handler = _copy_function(mptr);
3184 }
3185
3186 result = zend_call_function(&fci, &fcc);
3187
3188 if (!variadic) {
3189 for (i = 0; i < argc; i++) {
3190 zval_ptr_dtor(¶ms[i]);
3191 }
3192 efree(params);
3193 }
3194
3195 if (result == FAILURE) {
3196 zend_throw_exception_ex(reflection_exception_ptr, 0,
3197 "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3198 return;
3199 }
3200
3201 if (Z_TYPE(retval) != IS_UNDEF) {
3202 if (Z_ISREF(retval)) {
3203 zend_unwrap_reference(&retval);
3204 }
3205 ZVAL_COPY_VALUE(return_value, &retval);
3206 }
3207 }
3208 /* }}} */
3209
3210 /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
3211 Invokes the method. */
ZEND_METHOD(reflection_method,invoke)3212 ZEND_METHOD(reflection_method, invoke)
3213 {
3214 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3215 }
3216 /* }}} */
3217
3218 /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
3219 Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_method,invokeArgs)3220 ZEND_METHOD(reflection_method, invokeArgs)
3221 {
3222 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3223 }
3224 /* }}} */
3225
3226 /* {{{ proto public bool ReflectionMethod::isFinal()
3227 Returns whether this method is final */
ZEND_METHOD(reflection_method,isFinal)3228 ZEND_METHOD(reflection_method, isFinal)
3229 {
3230 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
3231 }
3232 /* }}} */
3233
3234 /* {{{ proto public bool ReflectionMethod::isAbstract()
3235 Returns whether this method is abstract */
ZEND_METHOD(reflection_method,isAbstract)3236 ZEND_METHOD(reflection_method, isAbstract)
3237 {
3238 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
3239 }
3240 /* }}} */
3241
3242 /* {{{ proto public bool ReflectionMethod::isPublic()
3243 Returns whether this method is public */
ZEND_METHOD(reflection_method,isPublic)3244 ZEND_METHOD(reflection_method, isPublic)
3245 {
3246 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3247 }
3248 /* }}} */
3249
3250 /* {{{ proto public bool ReflectionMethod::isPrivate()
3251 Returns whether this method is private */
ZEND_METHOD(reflection_method,isPrivate)3252 ZEND_METHOD(reflection_method, isPrivate)
3253 {
3254 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3255 }
3256 /* }}} */
3257
3258 /* {{{ proto public bool ReflectionMethod::isProtected()
3259 Returns whether this method is protected */
ZEND_METHOD(reflection_method,isProtected)3260 ZEND_METHOD(reflection_method, isProtected)
3261 {
3262 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3263 }
3264 /* }}} */
3265
3266 /* {{{ proto public bool ReflectionMethod::isStatic()
3267 Returns whether this method is static */
ZEND_METHOD(reflection_method,isStatic)3268 ZEND_METHOD(reflection_method, isStatic)
3269 {
3270 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
3271 }
3272 /* }}} */
3273
3274 /* {{{ proto public bool ReflectionFunction::isDeprecated()
3275 Returns whether this function is deprecated */
ZEND_METHOD(reflection_function,isDeprecated)3276 ZEND_METHOD(reflection_function, isDeprecated)
3277 {
3278 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
3279 }
3280 /* }}} */
3281
3282 /* {{{ proto public bool ReflectionFunction::isGenerator()
3283 Returns whether this function is a generator */
ZEND_METHOD(reflection_function,isGenerator)3284 ZEND_METHOD(reflection_function, isGenerator)
3285 {
3286 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_GENERATOR);
3287 }
3288 /* }}} */
3289
3290 /* {{{ proto public bool ReflectionFunction::isVariadic()
3291 Returns whether this function is variadic */
ZEND_METHOD(reflection_function,isVariadic)3292 ZEND_METHOD(reflection_function, isVariadic)
3293 {
3294 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC);
3295 }
3296 /* }}} */
3297
3298 /* {{{ proto public bool ReflectionFunction::inNamespace()
3299 Returns whether this function is defined in namespace */
ZEND_METHOD(reflection_function,inNamespace)3300 ZEND_METHOD(reflection_function, inNamespace)
3301 {
3302 zval *name;
3303 const char *backslash;
3304
3305 if (zend_parse_parameters_none() == FAILURE) {
3306 return;
3307 }
3308 if ((name = _default_load_name(getThis())) == NULL) {
3309 RETURN_FALSE;
3310 }
3311 if (Z_TYPE_P(name) == IS_STRING
3312 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3313 && backslash > Z_STRVAL_P(name))
3314 {
3315 RETURN_TRUE;
3316 }
3317 RETURN_FALSE;
3318 }
3319 /* }}} */
3320
3321 /* {{{ proto public string ReflectionFunction::getNamespaceName()
3322 Returns the name of namespace where this function is defined */
ZEND_METHOD(reflection_function,getNamespaceName)3323 ZEND_METHOD(reflection_function, getNamespaceName)
3324 {
3325 zval *name;
3326 const char *backslash;
3327
3328 if (zend_parse_parameters_none() == FAILURE) {
3329 return;
3330 }
3331 if ((name = _default_load_name(getThis())) == NULL) {
3332 RETURN_FALSE;
3333 }
3334 if (Z_TYPE_P(name) == IS_STRING
3335 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3336 && backslash > Z_STRVAL_P(name))
3337 {
3338 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
3339 }
3340 RETURN_EMPTY_STRING();
3341 }
3342 /* }}} */
3343
3344 /* {{{ proto public string ReflectionFunction::getShortName()
3345 Returns the short name of the function (without namespace part) */
ZEND_METHOD(reflection_function,getShortName)3346 ZEND_METHOD(reflection_function, getShortName)
3347 {
3348 zval *name;
3349 const char *backslash;
3350
3351 if (zend_parse_parameters_none() == FAILURE) {
3352 return;
3353 }
3354 if ((name = _default_load_name(getThis())) == NULL) {
3355 RETURN_FALSE;
3356 }
3357 if (Z_TYPE_P(name) == IS_STRING
3358 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3359 && backslash > Z_STRVAL_P(name))
3360 {
3361 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
3362 }
3363 ZVAL_COPY_DEREF(return_value, name);
3364 }
3365 /* }}} */
3366
3367 /* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
3368 Return whether the function has a return type */
ZEND_METHOD(reflection_function,hasReturnType)3369 ZEND_METHOD(reflection_function, hasReturnType)
3370 {
3371 reflection_object *intern;
3372 zend_function *fptr;
3373
3374 if (zend_parse_parameters_none() == FAILURE) {
3375 return;
3376 }
3377
3378 GET_REFLECTION_OBJECT_PTR(fptr);
3379
3380 RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3381 }
3382 /* }}} */
3383
3384 /* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
3385 Returns the return type associated with the function */
ZEND_METHOD(reflection_function,getReturnType)3386 ZEND_METHOD(reflection_function, getReturnType)
3387 {
3388 reflection_object *intern;
3389 zend_function *fptr;
3390
3391 if (zend_parse_parameters_none() == FAILURE) {
3392 return;
3393 }
3394
3395 GET_REFLECTION_OBJECT_PTR(fptr);
3396
3397 if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3398 RETURN_NULL();
3399 }
3400
3401 reflection_type_factory(_copy_function(fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, &fptr->common.arg_info[-1], return_value);
3402 }
3403 /* }}} */
3404
3405 /* {{{ proto public bool ReflectionMethod::isConstructor()
3406 Returns whether this method is the constructor */
ZEND_METHOD(reflection_method,isConstructor)3407 ZEND_METHOD(reflection_method, isConstructor)
3408 {
3409 reflection_object *intern;
3410 zend_function *mptr;
3411
3412 if (zend_parse_parameters_none() == FAILURE) {
3413 return;
3414 }
3415 GET_REFLECTION_OBJECT_PTR(mptr);
3416 /* we need to check if the ctor is the ctor of the class level we we
3417 * looking at since we might be looking at an inherited old style ctor
3418 * defined in base class. */
3419 RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
3420 }
3421 /* }}} */
3422
3423 /* {{{ proto public bool ReflectionMethod::isDestructor()
3424 Returns whether this method is static */
ZEND_METHOD(reflection_method,isDestructor)3425 ZEND_METHOD(reflection_method, isDestructor)
3426 {
3427 reflection_object *intern;
3428 zend_function *mptr;
3429
3430 if (zend_parse_parameters_none() == FAILURE) {
3431 return;
3432 }
3433 GET_REFLECTION_OBJECT_PTR(mptr);
3434 RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
3435 }
3436 /* }}} */
3437
3438 /* {{{ proto public int ReflectionMethod::getModifiers()
3439 Returns a bitfield of the access modifiers for this method */
ZEND_METHOD(reflection_method,getModifiers)3440 ZEND_METHOD(reflection_method, getModifiers)
3441 {
3442 reflection_object *intern;
3443 zend_function *mptr;
3444 uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_IMPLICIT_PUBLIC
3445 | ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL;
3446
3447 if (zend_parse_parameters_none() == FAILURE) {
3448 return;
3449 }
3450 GET_REFLECTION_OBJECT_PTR(mptr);
3451
3452 RETURN_LONG((mptr->common.fn_flags & keep_flags));
3453 }
3454 /* }}} */
3455
3456 /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
3457 Get the declaring class */
ZEND_METHOD(reflection_method,getDeclaringClass)3458 ZEND_METHOD(reflection_method, getDeclaringClass)
3459 {
3460 reflection_object *intern;
3461 zend_function *mptr;
3462
3463 GET_REFLECTION_OBJECT_PTR(mptr);
3464
3465 if (zend_parse_parameters_none() == FAILURE) {
3466 return;
3467 }
3468
3469 zend_reflection_class_factory(mptr->common.scope, return_value);
3470 }
3471 /* }}} */
3472
3473 /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
3474 Get the prototype */
ZEND_METHOD(reflection_method,getPrototype)3475 ZEND_METHOD(reflection_method, getPrototype)
3476 {
3477 reflection_object *intern;
3478 zend_function *mptr;
3479
3480 GET_REFLECTION_OBJECT_PTR(mptr);
3481
3482 if (zend_parse_parameters_none() == FAILURE) {
3483 return;
3484 }
3485
3486 if (!mptr->common.prototype) {
3487 zend_throw_exception_ex(reflection_exception_ptr, 0,
3488 "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
3489 return;
3490 }
3491
3492 reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
3493 }
3494 /* }}} */
3495
3496 /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
3497 Sets whether non-public methods can be invoked */
ZEND_METHOD(reflection_method,setAccessible)3498 ZEND_METHOD(reflection_method, setAccessible)
3499 {
3500 reflection_object *intern;
3501 zend_bool visible;
3502
3503 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
3504 return;
3505 }
3506
3507 intern = Z_REFLECTION_P(getThis());
3508
3509 intern->ignore_visibility = visible;
3510 }
3511 /* }}} */
3512
3513 /* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
3514 Constructor. Throws an Exception in case the given class constant does not exist */
ZEND_METHOD(reflection_class_constant,__construct)3515 ZEND_METHOD(reflection_class_constant, __construct)
3516 {
3517 zval *classname, *object, name, cname;
3518 zend_string *constname;
3519 reflection_object *intern;
3520 zend_class_entry *ce;
3521 zend_class_constant *constant = NULL;
3522
3523 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
3524 return;
3525 }
3526
3527 object = getThis();
3528 intern = Z_REFLECTION_P(object);
3529
3530 /* Find the class entry */
3531 switch (Z_TYPE_P(classname)) {
3532 case IS_STRING:
3533 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
3534 zend_throw_exception_ex(reflection_exception_ptr, 0,
3535 "Class %s does not exist", Z_STRVAL_P(classname));
3536 return;
3537 }
3538 break;
3539
3540 case IS_OBJECT:
3541 ce = Z_OBJCE_P(classname);
3542 break;
3543
3544 default:
3545 _DO_THROW("The parameter class is expected to be either a string or an object");
3546 /* returns out of this function */
3547 }
3548
3549 if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
3550 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
3551 return;
3552 }
3553
3554 ZVAL_STR_COPY(&name, constname);
3555 ZVAL_STR_COPY(&cname, ce->name);
3556
3557 intern->ptr = constant;
3558 intern->ref_type = REF_TYPE_CLASS_CONSTANT;
3559 intern->ce = constant->ce;
3560 intern->ignore_visibility = 0;
3561 reflection_update_property_name(object, &name);
3562 reflection_update_property_class(object, &cname);
3563 }
3564 /* }}} */
3565
3566 /* {{{ proto public string ReflectionClassConstant::__toString()
3567 Returns a string representation */
ZEND_METHOD(reflection_class_constant,__toString)3568 ZEND_METHOD(reflection_class_constant, __toString)
3569 {
3570 reflection_object *intern;
3571 zend_class_constant *ref;
3572 smart_str str = {0};
3573 zval name;
3574
3575 if (zend_parse_parameters_none() == FAILURE) {
3576 return;
3577 }
3578 GET_REFLECTION_OBJECT_PTR(ref);
3579 _default_get_name(getThis(), &name);
3580 _class_const_string(&str, Z_STRVAL(name), ref, "");
3581 zval_ptr_dtor(&name);
3582 RETURN_STR(smart_str_extract(&str));
3583 }
3584 /* }}} */
3585
3586 /* {{{ proto public string ReflectionClassConstant::getName()
3587 Returns the constant' name */
ZEND_METHOD(reflection_class_constant,getName)3588 ZEND_METHOD(reflection_class_constant, getName)
3589 {
3590 if (zend_parse_parameters_none() == FAILURE) {
3591 return;
3592 }
3593 _default_get_name(getThis(), return_value);
3594 }
3595 /* }}} */
3596
_class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)3597 static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
3598 {
3599 reflection_object *intern;
3600 zend_class_constant *ref;
3601
3602 if (zend_parse_parameters_none() == FAILURE) {
3603 return;
3604 }
3605 GET_REFLECTION_OBJECT_PTR(ref);
3606 RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
3607 }
3608 /* }}} */
3609
3610 /* {{{ proto public bool ReflectionClassConstant::isPublic()
3611 Returns whether this constant is public */
ZEND_METHOD(reflection_class_constant,isPublic)3612 ZEND_METHOD(reflection_class_constant, isPublic)
3613 {
3614 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
3615 }
3616 /* }}} */
3617
3618 /* {{{ proto public bool ReflectionClassConstant::isPrivate()
3619 Returns whether this constant is private */
ZEND_METHOD(reflection_class_constant,isPrivate)3620 ZEND_METHOD(reflection_class_constant, isPrivate)
3621 {
3622 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3623 }
3624 /* }}} */
3625
3626 /* {{{ proto public bool ReflectionClassConstant::isProtected()
3627 Returns whether this constant is protected */
ZEND_METHOD(reflection_class_constant,isProtected)3628 ZEND_METHOD(reflection_class_constant, isProtected)
3629 {
3630 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3631 }
3632 /* }}} */
3633
3634 /* {{{ proto public int ReflectionClassConstant::getModifiers()
3635 Returns a bitfield of the access modifiers for this constant */
ZEND_METHOD(reflection_class_constant,getModifiers)3636 ZEND_METHOD(reflection_class_constant, getModifiers)
3637 {
3638 reflection_object *intern;
3639 zend_class_constant *ref;
3640
3641 if (zend_parse_parameters_none() == FAILURE) {
3642 return;
3643 }
3644 GET_REFLECTION_OBJECT_PTR(ref);
3645
3646 RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
3647 }
3648 /* }}} */
3649
3650 /* {{{ proto public mixed ReflectionClassConstant::getValue()
3651 Returns this constant's value */
ZEND_METHOD(reflection_class_constant,getValue)3652 ZEND_METHOD(reflection_class_constant, getValue)
3653 {
3654 reflection_object *intern;
3655 zend_class_constant *ref;
3656
3657 if (zend_parse_parameters_none() == FAILURE) {
3658 return;
3659 }
3660 GET_REFLECTION_OBJECT_PTR(ref);
3661
3662 ZVAL_COPY_OR_DUP(return_value, &ref->value);
3663 if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
3664 zval_update_constant_ex(return_value, ref->ce);
3665 }
3666 }
3667 /* }}} */
3668
3669 /* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
3670 Get the declaring class */
ZEND_METHOD(reflection_class_constant,getDeclaringClass)3671 ZEND_METHOD(reflection_class_constant, getDeclaringClass)
3672 {
3673 reflection_object *intern;
3674 zend_class_constant *ref;
3675
3676 if (zend_parse_parameters_none() == FAILURE) {
3677 return;
3678 }
3679 GET_REFLECTION_OBJECT_PTR(ref);
3680
3681 zend_reflection_class_factory(ref->ce, return_value);
3682 }
3683 /* }}} */
3684
3685 /* {{{ proto public string ReflectionClassConstant::getDocComment()
3686 Returns the doc comment for this constant */
ZEND_METHOD(reflection_class_constant,getDocComment)3687 ZEND_METHOD(reflection_class_constant, getDocComment)
3688 {
3689 reflection_object *intern;
3690 zend_class_constant *ref;
3691
3692 if (zend_parse_parameters_none() == FAILURE) {
3693 return;
3694 }
3695 GET_REFLECTION_OBJECT_PTR(ref);
3696 if (ref->doc_comment) {
3697 RETURN_STR_COPY(ref->doc_comment);
3698 }
3699 RETURN_FALSE;
3700 }
3701 /* }}} */
3702
3703 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
3704 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class,export)3705 ZEND_METHOD(reflection_class, export)
3706 {
3707 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
3708 }
3709 /* }}} */
3710
3711 /* {{{ reflection_class_object_ctor */
reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS,int is_object)3712 static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
3713 {
3714 zval *argument;
3715 zval *object;
3716 zval classname;
3717 reflection_object *intern;
3718 zend_class_entry *ce;
3719
3720 if (is_object) {
3721 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &argument) == FAILURE) {
3722 return;
3723 }
3724 } else {
3725 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &argument) == FAILURE) {
3726 return;
3727 }
3728 }
3729
3730 object = getThis();
3731 intern = Z_REFLECTION_P(object);
3732
3733 if (Z_TYPE_P(argument) == IS_OBJECT) {
3734 ZVAL_STR_COPY(&classname, Z_OBJCE_P(argument)->name);
3735 reflection_update_property_name(object, &classname);
3736 intern->ptr = Z_OBJCE_P(argument);
3737 if (is_object) {
3738 ZVAL_COPY(&intern->obj, argument);
3739 }
3740 } else {
3741 convert_to_string_ex(argument);
3742 if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
3743 if (!EG(exception)) {
3744 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
3745 }
3746 return;
3747 }
3748
3749 ZVAL_STR_COPY(&classname, ce->name);
3750 reflection_update_property_name(object, &classname);
3751
3752 intern->ptr = ce;
3753 }
3754 intern->ref_type = REF_TYPE_OTHER;
3755 }
3756 /* }}} */
3757
3758 /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
3759 Constructor. Takes a string or an instance as an argument */
ZEND_METHOD(reflection_class,__construct)3760 ZEND_METHOD(reflection_class, __construct)
3761 {
3762 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3763 }
3764 /* }}} */
3765
3766 /* {{{ add_class_vars */
add_class_vars(zend_class_entry * ce,int statics,zval * return_value)3767 static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value)
3768 {
3769 zend_property_info *prop_info;
3770 zval *prop, prop_copy;
3771 zend_string *key;
3772
3773 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3774 if (((prop_info->flags & ZEND_ACC_SHADOW) &&
3775 prop_info->ce != ce) ||
3776 ((prop_info->flags & ZEND_ACC_PROTECTED) &&
3777 !zend_check_protected(prop_info->ce, ce)) ||
3778 ((prop_info->flags & ZEND_ACC_PRIVATE) &&
3779 prop_info->ce != ce)) {
3780 continue;
3781 }
3782 prop = NULL;
3783 if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
3784 prop = &ce->default_static_members_table[prop_info->offset];
3785 ZVAL_DEINDIRECT(prop);
3786 } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
3787 prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
3788 }
3789 if (!prop) {
3790 continue;
3791 }
3792
3793 /* copy: enforce read only access */
3794 ZVAL_DEREF(prop);
3795 ZVAL_COPY_OR_DUP(&prop_copy, prop);
3796
3797 /* this is necessary to make it able to work with default array
3798 * properties, returned to user */
3799 if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) {
3800 if (UNEXPECTED(zval_update_constant_ex(&prop_copy, NULL) != SUCCESS)) {
3801 return;
3802 }
3803 }
3804
3805 zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy);
3806 } ZEND_HASH_FOREACH_END();
3807 }
3808 /* }}} */
3809
3810 /* {{{ proto public array ReflectionClass::getStaticProperties()
3811 Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class,getStaticProperties)3812 ZEND_METHOD(reflection_class, getStaticProperties)
3813 {
3814 reflection_object *intern;
3815 zend_class_entry *ce;
3816
3817 if (zend_parse_parameters_none() == FAILURE) {
3818 return;
3819 }
3820
3821 GET_REFLECTION_OBJECT_PTR(ce);
3822
3823 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3824 return;
3825 }
3826
3827 array_init(return_value);
3828 add_class_vars(ce, 1, return_value);
3829 }
3830 /* }}} */
3831
3832 /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
3833 Returns the value of a static property */
ZEND_METHOD(reflection_class,getStaticPropertyValue)3834 ZEND_METHOD(reflection_class, getStaticPropertyValue)
3835 {
3836 reflection_object *intern;
3837 zend_class_entry *ce;
3838 zend_string *name;
3839 zval *prop, *def_value = NULL;
3840
3841 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
3842 return;
3843 }
3844
3845 GET_REFLECTION_OBJECT_PTR(ce);
3846
3847 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3848 return;
3849 }
3850 prop = zend_std_get_static_property(ce, name, 1);
3851 if (!prop) {
3852 if (def_value) {
3853 ZVAL_COPY(return_value, def_value);
3854 } else {
3855 zend_throw_exception_ex(reflection_exception_ptr, 0,
3856 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3857 }
3858 return;
3859 } else {
3860 ZVAL_COPY_DEREF(return_value, prop);
3861 }
3862 }
3863 /* }}} */
3864
3865 /* {{{ proto public void ReflectionClass::setStaticPropertyValue(string $name, mixed $value)
3866 Sets the value of a static property */
ZEND_METHOD(reflection_class,setStaticPropertyValue)3867 ZEND_METHOD(reflection_class, setStaticPropertyValue)
3868 {
3869 reflection_object *intern;
3870 zend_class_entry *ce;
3871 zend_string *name;
3872 zval *variable_ptr, *value;
3873
3874 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &value) == FAILURE) {
3875 return;
3876 }
3877
3878 GET_REFLECTION_OBJECT_PTR(ce);
3879
3880 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3881 return;
3882 }
3883 variable_ptr = zend_std_get_static_property(ce, name, 1);
3884 if (!variable_ptr) {
3885 zend_throw_exception_ex(reflection_exception_ptr, 0,
3886 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3887 return;
3888 }
3889 ZVAL_DEREF(variable_ptr);
3890 zval_ptr_dtor(variable_ptr);
3891 ZVAL_COPY(variable_ptr, value);
3892 }
3893 /* }}} */
3894
3895 /* {{{ proto public array ReflectionClass::getDefaultProperties()
3896 Returns an associative array containing copies of all default property values of the class */
ZEND_METHOD(reflection_class,getDefaultProperties)3897 ZEND_METHOD(reflection_class, getDefaultProperties)
3898 {
3899 reflection_object *intern;
3900 zend_class_entry *ce;
3901
3902 if (zend_parse_parameters_none() == FAILURE) {
3903 return;
3904 }
3905 GET_REFLECTION_OBJECT_PTR(ce);
3906 array_init(return_value);
3907 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3908 return;
3909 }
3910 add_class_vars(ce, 1, return_value);
3911 add_class_vars(ce, 0, return_value);
3912 }
3913 /* }}} */
3914
3915 /* {{{ proto public string ReflectionClass::__toString()
3916 Returns a string representation */
ZEND_METHOD(reflection_class,__toString)3917 ZEND_METHOD(reflection_class, __toString)
3918 {
3919 reflection_object *intern;
3920 zend_class_entry *ce;
3921 smart_str str = {0};
3922
3923 if (zend_parse_parameters_none() == FAILURE) {
3924 return;
3925 }
3926 GET_REFLECTION_OBJECT_PTR(ce);
3927 _class_string(&str, ce, &intern->obj, "");
3928 RETURN_STR(smart_str_extract(&str));
3929 }
3930 /* }}} */
3931
3932 /* {{{ proto public string ReflectionClass::getName()
3933 Returns the class' name */
ZEND_METHOD(reflection_class,getName)3934 ZEND_METHOD(reflection_class, getName)
3935 {
3936 if (zend_parse_parameters_none() == FAILURE) {
3937 return;
3938 }
3939 _default_get_name(getThis(), return_value);
3940 }
3941 /* }}} */
3942
3943 /* {{{ proto public bool ReflectionClass::isInternal()
3944 Returns whether this class is an internal class */
ZEND_METHOD(reflection_class,isInternal)3945 ZEND_METHOD(reflection_class, isInternal)
3946 {
3947 reflection_object *intern;
3948 zend_class_entry *ce;
3949
3950 if (zend_parse_parameters_none() == FAILURE) {
3951 return;
3952 }
3953 GET_REFLECTION_OBJECT_PTR(ce);
3954 RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
3955 }
3956 /* }}} */
3957
3958 /* {{{ proto public bool ReflectionClass::isUserDefined()
3959 Returns whether this class is user-defined */
ZEND_METHOD(reflection_class,isUserDefined)3960 ZEND_METHOD(reflection_class, isUserDefined)
3961 {
3962 reflection_object *intern;
3963 zend_class_entry *ce;
3964
3965 if (zend_parse_parameters_none() == FAILURE) {
3966 return;
3967 }
3968 GET_REFLECTION_OBJECT_PTR(ce);
3969 RETURN_BOOL(ce->type == ZEND_USER_CLASS);
3970 }
3971 /* }}} */
3972
3973 /* {{{ proto public bool ReflectionClass::isAnonymous()
3974 Returns whether this class is anonymous */
ZEND_METHOD(reflection_class,isAnonymous)3975 ZEND_METHOD(reflection_class, isAnonymous)
3976 {
3977 reflection_object *intern;
3978 zend_class_entry *ce;
3979
3980 if (zend_parse_parameters_none() == FAILURE) {
3981 return;
3982 }
3983 GET_REFLECTION_OBJECT_PTR(ce);
3984 RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
3985 }
3986 /* }}} */
3987
3988 /* {{{ proto public string ReflectionClass::getFileName()
3989 Returns the filename of the file this class was declared in */
ZEND_METHOD(reflection_class,getFileName)3990 ZEND_METHOD(reflection_class, getFileName)
3991 {
3992 reflection_object *intern;
3993 zend_class_entry *ce;
3994
3995 if (zend_parse_parameters_none() == FAILURE) {
3996 return;
3997 }
3998 GET_REFLECTION_OBJECT_PTR(ce);
3999 if (ce->type == ZEND_USER_CLASS) {
4000 RETURN_STR_COPY(ce->info.user.filename);
4001 }
4002 RETURN_FALSE;
4003 }
4004 /* }}} */
4005
4006 /* {{{ proto public int ReflectionClass::getStartLine()
4007 Returns the line this class' declaration starts at */
ZEND_METHOD(reflection_class,getStartLine)4008 ZEND_METHOD(reflection_class, getStartLine)
4009 {
4010 reflection_object *intern;
4011 zend_class_entry *ce;
4012
4013 if (zend_parse_parameters_none() == FAILURE) {
4014 return;
4015 }
4016 GET_REFLECTION_OBJECT_PTR(ce);
4017 if (ce->type == ZEND_USER_CLASS) {
4018 RETURN_LONG(ce->info.user.line_start);
4019 }
4020 RETURN_FALSE;
4021 }
4022 /* }}} */
4023
4024 /* {{{ proto public int ReflectionClass::getEndLine()
4025 Returns the line this class' declaration ends at */
ZEND_METHOD(reflection_class,getEndLine)4026 ZEND_METHOD(reflection_class, getEndLine)
4027 {
4028 reflection_object *intern;
4029 zend_class_entry *ce;
4030
4031 if (zend_parse_parameters_none() == FAILURE) {
4032 return;
4033 }
4034 GET_REFLECTION_OBJECT_PTR(ce);
4035 if (ce->type == ZEND_USER_CLASS) {
4036 RETURN_LONG(ce->info.user.line_end);
4037 }
4038 RETURN_FALSE;
4039 }
4040 /* }}} */
4041
4042 /* {{{ proto public string ReflectionClass::getDocComment()
4043 Returns the doc comment for this class */
ZEND_METHOD(reflection_class,getDocComment)4044 ZEND_METHOD(reflection_class, getDocComment)
4045 {
4046 reflection_object *intern;
4047 zend_class_entry *ce;
4048
4049 if (zend_parse_parameters_none() == FAILURE) {
4050 return;
4051 }
4052 GET_REFLECTION_OBJECT_PTR(ce);
4053 if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
4054 RETURN_STR_COPY(ce->info.user.doc_comment);
4055 }
4056 RETURN_FALSE;
4057 }
4058 /* }}} */
4059
4060 /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
4061 Returns the class' constructor if there is one, NULL otherwise */
ZEND_METHOD(reflection_class,getConstructor)4062 ZEND_METHOD(reflection_class, getConstructor)
4063 {
4064 reflection_object *intern;
4065 zend_class_entry *ce;
4066
4067 if (zend_parse_parameters_none() == FAILURE) {
4068 return;
4069 }
4070 GET_REFLECTION_OBJECT_PTR(ce);
4071
4072 if (ce->constructor) {
4073 reflection_method_factory(ce, ce->constructor, NULL, return_value);
4074 } else {
4075 RETURN_NULL();
4076 }
4077 }
4078 /* }}} */
4079
4080 /* {{{ proto public bool ReflectionClass::hasMethod(string name)
4081 Returns whether a method exists or not */
ZEND_METHOD(reflection_class,hasMethod)4082 ZEND_METHOD(reflection_class, hasMethod)
4083 {
4084 reflection_object *intern;
4085 zend_class_entry *ce;
4086 char *name, *lc_name;
4087 size_t name_len;
4088
4089 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
4090 return;
4091 }
4092
4093 GET_REFLECTION_OBJECT_PTR(ce);
4094 lc_name = zend_str_tolower_dup(name, name_len);
4095 if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4096 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0)
4097 || zend_hash_str_exists(&ce->function_table, lc_name, name_len)) {
4098 efree(lc_name);
4099 RETURN_TRUE;
4100 } else {
4101 efree(lc_name);
4102 RETURN_FALSE;
4103 }
4104 }
4105 /* }}} */
4106
4107 /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
4108 Returns the class' method specified by its name */
ZEND_METHOD(reflection_class,getMethod)4109 ZEND_METHOD(reflection_class, getMethod)
4110 {
4111 reflection_object *intern;
4112 zend_class_entry *ce;
4113 zend_function *mptr;
4114 zval obj_tmp;
4115 char *name, *lc_name;
4116 size_t name_len;
4117
4118 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
4119 return;
4120 }
4121
4122 GET_REFLECTION_OBJECT_PTR(ce);
4123 lc_name = zend_str_tolower_dup(name, name_len);
4124 if (ce == zend_ce_closure && !Z_ISUNDEF(intern->obj) && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4125 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4126 && (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
4127 {
4128 /* don't assign closure_object since we only reflect the invoke handler
4129 method and not the closure definition itself */
4130 reflection_method_factory(ce, mptr, NULL, return_value);
4131 efree(lc_name);
4132 } else if (ce == zend_ce_closure && Z_ISUNDEF(intern->obj) && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4133 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4134 && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
4135 /* don't assign closure_object since we only reflect the invoke handler
4136 method and not the closure definition itself */
4137 reflection_method_factory(ce, mptr, NULL, return_value);
4138 zval_ptr_dtor(&obj_tmp);
4139 efree(lc_name);
4140 } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lc_name, name_len)) != NULL) {
4141 reflection_method_factory(ce, mptr, NULL, return_value);
4142 efree(lc_name);
4143 } else {
4144 efree(lc_name);
4145 zend_throw_exception_ex(reflection_exception_ptr, 0,
4146 "Method %s does not exist", name);
4147 return;
4148 }
4149 }
4150 /* }}} */
4151
4152 /* {{{ _addmethod */
_addmethod(zend_function * mptr,zend_class_entry * ce,zval * retval,zend_long filter)4153 static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
4154 {
4155 if (mptr->common.fn_flags & filter) {
4156 zval method;
4157 reflection_method_factory(ce, mptr, NULL, &method);
4158 add_next_index_zval(retval, &method);
4159 }
4160 }
4161 /* }}} */
4162
4163 /* {{{ _addmethod */
_addmethod_va(zval * el,int num_args,va_list args,zend_hash_key * hash_key)4164 static int _addmethod_va(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
4165 {
4166 zend_function *mptr = (zend_function*)Z_PTR_P(el);
4167 zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4168 zval *retval = va_arg(args, zval*);
4169 long filter = va_arg(args, long);
4170
4171 _addmethod(mptr, ce, retval, filter);
4172 return ZEND_HASH_APPLY_KEEP;
4173 }
4174 /* }}} */
4175
4176 /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
4177 Returns an array of this class' methods */
ZEND_METHOD(reflection_class,getMethods)4178 ZEND_METHOD(reflection_class, getMethods)
4179 {
4180 reflection_object *intern;
4181 zend_class_entry *ce;
4182 zend_long filter = 0;
4183 zend_bool filter_is_null = 1;
4184
4185 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4186 return;
4187 }
4188
4189 if (filter_is_null) {
4190 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
4191 }
4192
4193 GET_REFLECTION_OBJECT_PTR(ce);
4194
4195 array_init(return_value);
4196 zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter);
4197
4198 if (instanceof_function(ce, zend_ce_closure)) {
4199 zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
4200 zval obj_tmp;
4201 zend_object *obj;
4202 if (!has_obj) {
4203 object_init_ex(&obj_tmp, ce);
4204 obj = Z_OBJ(obj_tmp);
4205 } else {
4206 obj = Z_OBJ(intern->obj);
4207 }
4208 zend_function *closure = zend_get_closure_invoke_method(obj);
4209 if (closure) {
4210 _addmethod(closure, ce, return_value, filter);
4211 }
4212 if (!has_obj) {
4213 zval_ptr_dtor(&obj_tmp);
4214 }
4215 }
4216 }
4217 /* }}} */
4218
4219 /* {{{ proto public bool ReflectionClass::hasProperty(string name)
4220 Returns whether a property exists or not */
ZEND_METHOD(reflection_class,hasProperty)4221 ZEND_METHOD(reflection_class, hasProperty)
4222 {
4223 reflection_object *intern;
4224 zend_property_info *property_info;
4225 zend_class_entry *ce;
4226 zend_string *name;
4227 zval property;
4228
4229 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4230 return;
4231 }
4232
4233 GET_REFLECTION_OBJECT_PTR(ce);
4234 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4235 if (property_info->flags & ZEND_ACC_SHADOW) {
4236 RETURN_FALSE;
4237 }
4238 RETURN_TRUE;
4239 } else {
4240 if (Z_TYPE(intern->obj) != IS_UNDEF && Z_OBJ_HANDLER(intern->obj, has_property)) {
4241 ZVAL_STR_COPY(&property, name);
4242 if (Z_OBJ_HANDLER(intern->obj, has_property)(&intern->obj, &property, 2, NULL)) {
4243 zval_ptr_dtor(&property);
4244 RETURN_TRUE;
4245 }
4246 zval_ptr_dtor(&property);
4247 }
4248 RETURN_FALSE;
4249 }
4250 }
4251 /* }}} */
4252
4253 /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
4254 Returns the class' property specified by its name */
ZEND_METHOD(reflection_class,getProperty)4255 ZEND_METHOD(reflection_class, getProperty)
4256 {
4257 reflection_object *intern;
4258 zend_class_entry *ce, *ce2;
4259 zend_property_info *property_info;
4260 zend_string *name, *classname;
4261 char *tmp, *str_name;
4262 size_t classname_len, str_name_len;
4263
4264 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4265 return;
4266 }
4267
4268 GET_REFLECTION_OBJECT_PTR(ce);
4269 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4270 if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
4271 reflection_property_factory(ce, name, property_info, return_value);
4272 return;
4273 }
4274 } else if (Z_TYPE(intern->obj) != IS_UNDEF) {
4275 /* Check for dynamic properties */
4276 if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(&intern->obj), name)) {
4277 zend_property_info property_info_tmp;
4278 property_info_tmp.flags = ZEND_ACC_IMPLICIT_PUBLIC;
4279 property_info_tmp.name = name;
4280 property_info_tmp.doc_comment = NULL;
4281 property_info_tmp.ce = ce;
4282
4283 reflection_property_factory(ce, name, &property_info_tmp, return_value);
4284 return;
4285 }
4286 }
4287 str_name = ZSTR_VAL(name);
4288 if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
4289 classname_len = tmp - ZSTR_VAL(name);
4290 classname = zend_string_alloc(classname_len, 0);
4291 zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
4292 ZSTR_VAL(classname)[classname_len] = '\0';
4293 str_name_len = ZSTR_LEN(name) - (classname_len + 2);
4294 str_name = tmp + 2;
4295
4296 ce2 = zend_lookup_class(classname);
4297 if (!ce2) {
4298 if (!EG(exception)) {
4299 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", ZSTR_VAL(classname));
4300 }
4301 zend_string_release_ex(classname, 0);
4302 return;
4303 }
4304 zend_string_release_ex(classname, 0);
4305
4306 if (!instanceof_function(ce, ce2)) {
4307 zend_throw_exception_ex(reflection_exception_ptr, -1, "Fully qualified property name %s::%s does not specify a base class of %s", ZSTR_VAL(ce2->name), str_name, ZSTR_VAL(ce->name));
4308 return;
4309 }
4310 ce = ce2;
4311
4312 if ((property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len)) != NULL && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
4313 reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
4314 return;
4315 }
4316 }
4317 zend_throw_exception_ex(reflection_exception_ptr, 0,
4318 "Property %s does not exist", str_name);
4319 }
4320 /* }}} */
4321
4322 /* {{{ _addproperty */
_addproperty(zval * el,int num_args,va_list args,zend_hash_key * hash_key)4323 static int _addproperty(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
4324 {
4325 zval property;
4326 zend_property_info *pptr = (zend_property_info*)Z_PTR_P(el);
4327 zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4328 zval *retval = va_arg(args, zval*);
4329 long filter = va_arg(args, long);
4330
4331 if (pptr->flags & ZEND_ACC_SHADOW) {
4332 return 0;
4333 }
4334
4335 if (pptr->flags & filter) {
4336 const char *class_name, *prop_name;
4337 size_t prop_name_len;
4338 zend_unmangle_property_name_ex(pptr->name, &class_name, &prop_name, &prop_name_len);
4339 reflection_property_factory_str(ce, prop_name, prop_name_len, pptr, &property);
4340 add_next_index_zval(retval, &property);
4341 }
4342 return 0;
4343 }
4344 /* }}} */
4345
4346 /* {{{ _adddynproperty */
_adddynproperty(zval * ptr,int num_args,va_list args,zend_hash_key * hash_key)4347 static int _adddynproperty(zval *ptr, int num_args, va_list args, zend_hash_key *hash_key)
4348 {
4349 zval property;
4350 zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4351 zval *retval = va_arg(args, zval*);
4352
4353 /* under some circumstances, the properties hash table may contain numeric
4354 * properties (e.g. when casting from array). This is a WONT FIX bug, at
4355 * least for the moment. Ignore these */
4356 if (hash_key->key == NULL) {
4357 return 0;
4358 }
4359
4360 if (ZSTR_VAL(hash_key->key)[0] == '\0') {
4361 return 0; /* non public cannot be dynamic */
4362 }
4363
4364 if (zend_get_property_info(ce, hash_key->key, 1) == NULL) {
4365 zend_property_info property_info;
4366
4367 property_info.doc_comment = NULL;
4368 property_info.flags = ZEND_ACC_IMPLICIT_PUBLIC;
4369 property_info.name = hash_key->key;
4370 property_info.ce = ce;
4371 property_info.offset = -1;
4372 reflection_property_factory(ce, hash_key->key, &property_info, &property);
4373 add_next_index_zval(retval, &property);
4374 }
4375 return 0;
4376 }
4377 /* }}} */
4378
4379 /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
4380 Returns an array of this class' properties */
ZEND_METHOD(reflection_class,getProperties)4381 ZEND_METHOD(reflection_class, getProperties)
4382 {
4383 reflection_object *intern;
4384 zend_class_entry *ce;
4385 zend_long filter = 0;
4386 zend_bool filter_is_null = 1;
4387
4388 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4389 return;
4390 }
4391
4392 if (filter_is_null) {
4393 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
4394 }
4395
4396 GET_REFLECTION_OBJECT_PTR(ce);
4397
4398 array_init(return_value);
4399 zend_hash_apply_with_arguments(&ce->properties_info, (apply_func_args_t) _addproperty, 3, &ce, return_value, filter);
4400
4401 if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0 && Z_OBJ_HT(intern->obj)->get_properties) {
4402 HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(&intern->obj);
4403 zend_hash_apply_with_arguments(properties, (apply_func_args_t) _adddynproperty, 2, &ce, return_value);
4404 }
4405 }
4406 /* }}} */
4407
4408 /* {{{ proto public bool ReflectionClass::hasConstant(string name)
4409 Returns whether a constant exists or not */
ZEND_METHOD(reflection_class,hasConstant)4410 ZEND_METHOD(reflection_class, hasConstant)
4411 {
4412 reflection_object *intern;
4413 zend_class_entry *ce;
4414 zend_string *name;
4415
4416 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4417 return;
4418 }
4419
4420 GET_REFLECTION_OBJECT_PTR(ce);
4421 if (zend_hash_exists(&ce->constants_table, name)) {
4422 RETURN_TRUE;
4423 } else {
4424 RETURN_FALSE;
4425 }
4426 }
4427 /* }}} */
4428
4429 /* {{{ proto public array ReflectionClass::getConstants()
4430 Returns an associative array containing this class' constants and their values */
ZEND_METHOD(reflection_class,getConstants)4431 ZEND_METHOD(reflection_class, getConstants)
4432 {
4433 reflection_object *intern;
4434 zend_class_entry *ce;
4435 zend_string *key;
4436 zend_class_constant *c;
4437 zval val;
4438
4439 if (zend_parse_parameters_none() == FAILURE) {
4440 return;
4441 }
4442 GET_REFLECTION_OBJECT_PTR(ce);
4443 array_init(return_value);
4444 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
4445 if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4446 zend_array_destroy(Z_ARRVAL_P(return_value));
4447 RETURN_NULL();
4448 }
4449 ZVAL_COPY_OR_DUP(&val, &c->value);
4450 zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
4451 } ZEND_HASH_FOREACH_END();
4452 }
4453 /* }}} */
4454
4455 /* {{{ proto public array ReflectionClass::getReflectionConstants()
4456 Returns an associative array containing this class' constants as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstants)4457 ZEND_METHOD(reflection_class, getReflectionConstants)
4458 {
4459 reflection_object *intern;
4460 zend_class_entry *ce;
4461 zend_string *name;
4462 zend_class_constant *constant;
4463
4464 if (zend_parse_parameters_none() == FAILURE) {
4465 return;
4466 }
4467 GET_REFLECTION_OBJECT_PTR(ce);
4468 array_init(return_value);
4469 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
4470 zval class_const;
4471 reflection_class_constant_factory(ce, name, constant, &class_const);
4472 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
4473 } ZEND_HASH_FOREACH_END();
4474 }
4475 /* }}} */
4476
4477 /* {{{ proto public mixed ReflectionClass::getConstant(string name)
4478 Returns the class' constant specified by its name */
ZEND_METHOD(reflection_class,getConstant)4479 ZEND_METHOD(reflection_class, getConstant)
4480 {
4481 reflection_object *intern;
4482 zend_class_entry *ce;
4483 zend_class_constant *c;
4484 zend_string *name;
4485
4486 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4487 return;
4488 }
4489
4490 GET_REFLECTION_OBJECT_PTR(ce);
4491 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
4492 if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4493 return;
4494 }
4495 } ZEND_HASH_FOREACH_END();
4496 if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4497 RETURN_FALSE;
4498 }
4499 ZVAL_COPY_OR_DUP(return_value, &c->value);
4500 }
4501 /* }}} */
4502
4503 /* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
4504 Returns the class' constant as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstant)4505 ZEND_METHOD(reflection_class, getReflectionConstant)
4506 {
4507 reflection_object *intern;
4508 zend_class_entry *ce;
4509 zend_class_constant *constant;
4510 zend_string *name;
4511
4512 GET_REFLECTION_OBJECT_PTR(ce);
4513 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4514 return;
4515 }
4516
4517 if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4518 RETURN_FALSE;
4519 }
4520 reflection_class_constant_factory(ce, name, constant, return_value);
4521 }
4522 /* }}} */
4523
4524 /* {{{ _class_check_flag */
_class_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)4525 static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
4526 {
4527 reflection_object *intern;
4528 zend_class_entry *ce;
4529
4530 if (zend_parse_parameters_none() == FAILURE) {
4531 return;
4532 }
4533 GET_REFLECTION_OBJECT_PTR(ce);
4534 RETVAL_BOOL(ce->ce_flags & mask);
4535 }
4536 /* }}} */
4537
4538 /* {{{ proto public bool ReflectionClass::isInstantiable()
4539 Returns whether this class is instantiable */
ZEND_METHOD(reflection_class,isInstantiable)4540 ZEND_METHOD(reflection_class, isInstantiable)
4541 {
4542 reflection_object *intern;
4543 zend_class_entry *ce;
4544
4545 if (zend_parse_parameters_none() == FAILURE) {
4546 return;
4547 }
4548 GET_REFLECTION_OBJECT_PTR(ce);
4549 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4550 RETURN_FALSE;
4551 }
4552
4553 /* Basically, the class is instantiable. Though, if there is a constructor
4554 * and it is not publicly accessible, it isn't! */
4555 if (!ce->constructor) {
4556 RETURN_TRUE;
4557 }
4558
4559 RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
4560 }
4561 /* }}} */
4562
4563 /* {{{ proto public bool ReflectionClass::isCloneable()
4564 Returns whether this class is cloneable */
ZEND_METHOD(reflection_class,isCloneable)4565 ZEND_METHOD(reflection_class, isCloneable)
4566 {
4567 reflection_object *intern;
4568 zend_class_entry *ce;
4569 zval obj;
4570
4571 if (zend_parse_parameters_none() == FAILURE) {
4572 return;
4573 }
4574 GET_REFLECTION_OBJECT_PTR(ce);
4575 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4576 RETURN_FALSE;
4577 }
4578 if (!Z_ISUNDEF(intern->obj)) {
4579 if (ce->clone) {
4580 RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4581 } else {
4582 RETURN_BOOL(Z_OBJ_HANDLER(intern->obj, clone_obj) != NULL);
4583 }
4584 } else {
4585 if (ce->clone) {
4586 RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4587 } else {
4588 if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
4589 return;
4590 }
4591 /* We're not calling the constructor, so don't call the destructor either. */
4592 zend_object_store_ctor_failed(Z_OBJ(obj));
4593 RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
4594 zval_ptr_dtor(&obj);
4595 }
4596 }
4597 }
4598 /* }}} */
4599
4600 /* {{{ proto public bool ReflectionClass::isInterface()
4601 Returns whether this is an interface or a class */
ZEND_METHOD(reflection_class,isInterface)4602 ZEND_METHOD(reflection_class, isInterface)
4603 {
4604 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
4605 }
4606 /* }}} */
4607
4608 /* {{{ proto public bool ReflectionClass::isTrait()
4609 Returns whether this is a trait */
ZEND_METHOD(reflection_class,isTrait)4610 ZEND_METHOD(reflection_class, isTrait)
4611 {
4612 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT);
4613 }
4614 /* }}} */
4615
4616 /* {{{ proto public bool ReflectionClass::isFinal()
4617 Returns whether this class is final */
ZEND_METHOD(reflection_class,isFinal)4618 ZEND_METHOD(reflection_class, isFinal)
4619 {
4620 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
4621 }
4622 /* }}} */
4623
4624 /* {{{ proto public bool ReflectionClass::isAbstract()
4625 Returns whether this class is abstract */
ZEND_METHOD(reflection_class,isAbstract)4626 ZEND_METHOD(reflection_class, isAbstract)
4627 {
4628 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
4629 }
4630 /* }}} */
4631
4632 /* {{{ proto public int ReflectionClass::getModifiers()
4633 Returns a bitfield of the access modifiers for this class */
ZEND_METHOD(reflection_class,getModifiers)4634 ZEND_METHOD(reflection_class, getModifiers)
4635 {
4636 reflection_object *intern;
4637 zend_class_entry *ce;
4638 uint32_t keep_flags = ZEND_ACC_FINAL
4639 | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4640
4641 if (zend_parse_parameters_none() == FAILURE) {
4642 return;
4643 }
4644 GET_REFLECTION_OBJECT_PTR(ce);
4645
4646 RETURN_LONG((ce->ce_flags & keep_flags));
4647 }
4648 /* }}} */
4649
4650 /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
4651 Returns whether the given object is an instance of this class */
ZEND_METHOD(reflection_class,isInstance)4652 ZEND_METHOD(reflection_class, isInstance)
4653 {
4654 reflection_object *intern;
4655 zend_class_entry *ce;
4656 zval *object;
4657
4658 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
4659 return;
4660 }
4661 GET_REFLECTION_OBJECT_PTR(ce);
4662 RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
4663 }
4664 /* }}} */
4665
4666 /* {{{ proto public stdclass ReflectionClass::newInstance(mixed* args, ...)
4667 Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstance)4668 ZEND_METHOD(reflection_class, newInstance)
4669 {
4670 zval retval;
4671 reflection_object *intern;
4672 zend_class_entry *ce, *old_scope;
4673 zend_function *constructor;
4674
4675 GET_REFLECTION_OBJECT_PTR(ce);
4676
4677 if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4678 return;
4679 }
4680
4681 old_scope = EG(fake_scope);
4682 EG(fake_scope) = ce;
4683 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4684 EG(fake_scope) = old_scope;
4685
4686 /* Run the constructor if there is one */
4687 if (constructor) {
4688 zval *params = NULL;
4689 int ret, i, num_args = 0;
4690 zend_fcall_info fci;
4691 zend_fcall_info_cache fcc;
4692
4693 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4694 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4695 zval_ptr_dtor(return_value);
4696 RETURN_NULL();
4697 }
4698
4699 if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", ¶ms, &num_args) == FAILURE) {
4700 zval_ptr_dtor(return_value);
4701 RETURN_FALSE;
4702 }
4703
4704 for (i = 0; i < num_args; i++) {
4705 Z_TRY_ADDREF(params[i]);
4706 }
4707
4708 fci.size = sizeof(fci);
4709 ZVAL_UNDEF(&fci.function_name);
4710 fci.object = Z_OBJ_P(return_value);
4711 fci.retval = &retval;
4712 fci.param_count = num_args;
4713 fci.params = params;
4714 fci.no_separation = 1;
4715
4716 fcc.function_handler = constructor;
4717 fcc.called_scope = Z_OBJCE_P(return_value);
4718 fcc.object = Z_OBJ_P(return_value);
4719
4720 ret = zend_call_function(&fci, &fcc);
4721 zval_ptr_dtor(&retval);
4722 for (i = 0; i < num_args; i++) {
4723 zval_ptr_dtor(¶ms[i]);
4724 }
4725
4726 if (EG(exception)) {
4727 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4728 }
4729 if (ret == FAILURE) {
4730 php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4731 zval_ptr_dtor(return_value);
4732 RETURN_NULL();
4733 }
4734 } else if (ZEND_NUM_ARGS()) {
4735 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4736 }
4737 }
4738 /* }}} */
4739
4740 /* {{{ proto public stdclass ReflectionClass::newInstanceWithoutConstructor()
4741 Returns an instance of this class without invoking its constructor */
ZEND_METHOD(reflection_class,newInstanceWithoutConstructor)4742 ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
4743 {
4744 reflection_object *intern;
4745 zend_class_entry *ce;
4746
4747 GET_REFLECTION_OBJECT_PTR(ce);
4748
4749 if (ce->create_object != NULL && ce->ce_flags & ZEND_ACC_FINAL) {
4750 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s is an internal class marked as final that cannot be instantiated without invoking its constructor", ZSTR_VAL(ce->name));
4751 return;
4752 }
4753
4754 object_init_ex(return_value, ce);
4755 }
4756 /* }}} */
4757
4758 /* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
4759 Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstanceArgs)4760 ZEND_METHOD(reflection_class, newInstanceArgs)
4761 {
4762 zval retval, *val;
4763 reflection_object *intern;
4764 zend_class_entry *ce, *old_scope;
4765 int ret, i, argc = 0;
4766 HashTable *args;
4767 zend_function *constructor;
4768
4769 GET_REFLECTION_OBJECT_PTR(ce);
4770
4771 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
4772 return;
4773 }
4774
4775 if (ZEND_NUM_ARGS() > 0) {
4776 argc = args->nNumOfElements;
4777 }
4778
4779 if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4780 return;
4781 }
4782
4783 old_scope = EG(fake_scope);
4784 EG(fake_scope) = ce;
4785 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4786 EG(fake_scope) = old_scope;
4787
4788 /* Run the constructor if there is one */
4789 if (constructor) {
4790 zval *params = NULL;
4791 zend_fcall_info fci;
4792 zend_fcall_info_cache fcc;
4793
4794 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4795 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4796 zval_ptr_dtor(return_value);
4797 RETURN_NULL();
4798 }
4799
4800 if (argc) {
4801 params = safe_emalloc(sizeof(zval), argc, 0);
4802 argc = 0;
4803 ZEND_HASH_FOREACH_VAL(args, val) {
4804 ZVAL_COPY(¶ms[argc], val);
4805 argc++;
4806 } ZEND_HASH_FOREACH_END();
4807 }
4808
4809 fci.size = sizeof(fci);
4810 ZVAL_UNDEF(&fci.function_name);
4811 fci.object = Z_OBJ_P(return_value);
4812 fci.retval = &retval;
4813 fci.param_count = argc;
4814 fci.params = params;
4815 fci.no_separation = 1;
4816
4817 fcc.function_handler = constructor;
4818 fcc.called_scope = Z_OBJCE_P(return_value);
4819 fcc.object = Z_OBJ_P(return_value);
4820
4821 ret = zend_call_function(&fci, &fcc);
4822 zval_ptr_dtor(&retval);
4823 if (params) {
4824 for (i = 0; i < argc; i++) {
4825 zval_ptr_dtor(¶ms[i]);
4826 }
4827 efree(params);
4828 }
4829
4830 if (EG(exception)) {
4831 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4832 }
4833 if (ret == FAILURE) {
4834 zval_ptr_dtor(&retval);
4835 php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4836 zval_ptr_dtor(return_value);
4837 RETURN_NULL();
4838 }
4839 } else if (argc) {
4840 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4841 }
4842 }
4843 /* }}} */
4844
4845 /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
4846 Returns an array of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaces)4847 ZEND_METHOD(reflection_class, getInterfaces)
4848 {
4849 reflection_object *intern;
4850 zend_class_entry *ce;
4851
4852 if (zend_parse_parameters_none() == FAILURE) {
4853 return;
4854 }
4855 GET_REFLECTION_OBJECT_PTR(ce);
4856
4857 if (ce->num_interfaces) {
4858 uint32_t i;
4859
4860 array_init(return_value);
4861 for (i=0; i < ce->num_interfaces; i++) {
4862 zval interface;
4863 zend_reflection_class_factory(ce->interfaces[i], &interface);
4864 zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface);
4865 }
4866 } else {
4867 ZVAL_EMPTY_ARRAY(return_value);
4868 }
4869 }
4870 /* }}} */
4871
4872 /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
4873 Returns an array of names of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaceNames)4874 ZEND_METHOD(reflection_class, getInterfaceNames)
4875 {
4876 reflection_object *intern;
4877 zend_class_entry *ce;
4878 uint32_t i;
4879
4880 if (zend_parse_parameters_none() == FAILURE) {
4881 return;
4882 }
4883 GET_REFLECTION_OBJECT_PTR(ce);
4884
4885 if (!ce->num_interfaces) {
4886 /* Return an empty array if this class implements no interfaces */
4887 ZVAL_EMPTY_ARRAY(return_value);
4888 return;
4889 }
4890
4891 array_init(return_value);
4892
4893 for (i=0; i < ce->num_interfaces; i++) {
4894 add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
4895 }
4896 }
4897 /* }}} */
4898
4899 /* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
4900 Returns an array of traits used by this class */
ZEND_METHOD(reflection_class,getTraits)4901 ZEND_METHOD(reflection_class, getTraits)
4902 {
4903 reflection_object *intern;
4904 zend_class_entry *ce;
4905 uint32_t i;
4906
4907 if (zend_parse_parameters_none() == FAILURE) {
4908 return;
4909 }
4910 GET_REFLECTION_OBJECT_PTR(ce);
4911
4912 if (!ce->num_traits) {
4913 ZVAL_EMPTY_ARRAY(return_value);
4914 return;
4915 }
4916
4917 array_init(return_value);
4918
4919 for (i=0; i < ce->num_traits; i++) {
4920 zval trait;
4921 zend_reflection_class_factory(ce->traits[i], &trait);
4922 zend_hash_update(Z_ARRVAL_P(return_value), ce->traits[i]->name, &trait);
4923 }
4924 }
4925 /* }}} */
4926
4927 /* {{{ proto public String[] ReflectionClass::getTraitNames()
4928 Returns an array of names of traits used by this class */
ZEND_METHOD(reflection_class,getTraitNames)4929 ZEND_METHOD(reflection_class, getTraitNames)
4930 {
4931 reflection_object *intern;
4932 zend_class_entry *ce;
4933 uint32_t i;
4934
4935 if (zend_parse_parameters_none() == FAILURE) {
4936 return;
4937 }
4938 GET_REFLECTION_OBJECT_PTR(ce);
4939
4940 if (!ce->num_traits) {
4941 ZVAL_EMPTY_ARRAY(return_value);
4942 return;
4943 }
4944
4945 array_init(return_value);
4946
4947 for (i=0; i < ce->num_traits; i++) {
4948 add_next_index_str(return_value, zend_string_copy(ce->traits[i]->name));
4949 }
4950 }
4951 /* }}} */
4952
4953 /* {{{ proto public array ReflectionClass::getTraitAliases()
4954 Returns an array of trait aliases */
ZEND_METHOD(reflection_class,getTraitAliases)4955 ZEND_METHOD(reflection_class, getTraitAliases)
4956 {
4957 reflection_object *intern;
4958 zend_class_entry *ce;
4959
4960 if (zend_parse_parameters_none() == FAILURE) {
4961 return;
4962 }
4963 GET_REFLECTION_OBJECT_PTR(ce);
4964
4965
4966 if (ce->trait_aliases) {
4967 uint32_t i = 0;
4968
4969 array_init(return_value);
4970 while (ce->trait_aliases[i]) {
4971 zend_string *mname;
4972 zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method;
4973
4974 if (ce->trait_aliases[i]->alias) {
4975
4976 mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
4977 snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name));
4978 add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
4979 }
4980 i++;
4981 }
4982 } else {
4983 ZVAL_EMPTY_ARRAY(return_value);
4984 }
4985 }
4986 /* }}} */
4987
4988 /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
4989 Returns the class' parent class, or, if none exists, FALSE */
ZEND_METHOD(reflection_class,getParentClass)4990 ZEND_METHOD(reflection_class, getParentClass)
4991 {
4992 reflection_object *intern;
4993 zend_class_entry *ce;
4994
4995 if (zend_parse_parameters_none() == FAILURE) {
4996 return;
4997 }
4998 GET_REFLECTION_OBJECT_PTR(ce);
4999
5000 if (ce->parent) {
5001 zend_reflection_class_factory(ce->parent, return_value);
5002 } else {
5003 RETURN_FALSE;
5004 }
5005 }
5006 /* }}} */
5007
5008 /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
5009 Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,isSubclassOf)5010 ZEND_METHOD(reflection_class, isSubclassOf)
5011 {
5012 reflection_object *intern, *argument;
5013 zend_class_entry *ce, *class_ce;
5014 zval *class_name;
5015
5016 GET_REFLECTION_OBJECT_PTR(ce);
5017
5018 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
5019 return;
5020 }
5021
5022 switch (Z_TYPE_P(class_name)) {
5023 case IS_STRING:
5024 if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
5025 zend_throw_exception_ex(reflection_exception_ptr, 0,
5026 "Class %s does not exist", Z_STRVAL_P(class_name));
5027 return;
5028 }
5029 break;
5030 case IS_OBJECT:
5031 if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
5032 argument = Z_REFLECTION_P(class_name);
5033 if (argument->ptr == NULL) {
5034 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5035 return;
5036 }
5037 class_ce = argument->ptr;
5038 break;
5039 }
5040 /* no break */
5041 default:
5042 zend_throw_exception_ex(reflection_exception_ptr, 0,
5043 "Parameter one must either be a string or a ReflectionClass object");
5044 return;
5045 }
5046
5047 RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
5048 }
5049 /* }}} */
5050
5051 /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
5052 Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,implementsInterface)5053 ZEND_METHOD(reflection_class, implementsInterface)
5054 {
5055 reflection_object *intern, *argument;
5056 zend_class_entry *ce, *interface_ce;
5057 zval *interface;
5058
5059 GET_REFLECTION_OBJECT_PTR(ce);
5060
5061 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
5062 return;
5063 }
5064
5065 switch (Z_TYPE_P(interface)) {
5066 case IS_STRING:
5067 if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
5068 zend_throw_exception_ex(reflection_exception_ptr, 0,
5069 "Interface %s does not exist", Z_STRVAL_P(interface));
5070 return;
5071 }
5072 break;
5073 case IS_OBJECT:
5074 if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
5075 argument = Z_REFLECTION_P(interface);
5076 if (argument->ptr == NULL) {
5077 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5078 return;
5079 }
5080 interface_ce = argument->ptr;
5081 break;
5082 }
5083 /* no break */
5084 default:
5085 zend_throw_exception_ex(reflection_exception_ptr, 0,
5086 "Parameter one must either be a string or a ReflectionClass object");
5087 return;
5088 }
5089
5090 if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
5091 zend_throw_exception_ex(reflection_exception_ptr, 0,
5092 "%s is not an interface", ZSTR_VAL(interface_ce->name));
5093 return;
5094 }
5095 RETURN_BOOL(instanceof_function(ce, interface_ce));
5096 }
5097 /* }}} */
5098
5099 /* {{{ proto public bool ReflectionClass::isIterable()
5100 Returns whether this class is iterable (can be used inside foreach) */
ZEND_METHOD(reflection_class,isIterable)5101 ZEND_METHOD(reflection_class, isIterable)
5102 {
5103 reflection_object *intern;
5104 zend_class_entry *ce;
5105
5106 if (zend_parse_parameters_none() == FAILURE) {
5107 return;
5108 }
5109
5110 GET_REFLECTION_OBJECT_PTR(ce);
5111
5112 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
5113 ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
5114 RETURN_FALSE;
5115 }
5116
5117 RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable));
5118 }
5119 /* }}} */
5120
5121 /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
5122 Returns NULL or the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtension)5123 ZEND_METHOD(reflection_class, getExtension)
5124 {
5125 reflection_object *intern;
5126 zend_class_entry *ce;
5127
5128 if (zend_parse_parameters_none() == FAILURE) {
5129 return;
5130 }
5131
5132 GET_REFLECTION_OBJECT_PTR(ce);
5133
5134 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5135 reflection_extension_factory(return_value, ce->info.internal.module->name);
5136 }
5137 }
5138 /* }}} */
5139
5140 /* {{{ proto public string|false ReflectionClass::getExtensionName()
5141 Returns false or the name of the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtensionName)5142 ZEND_METHOD(reflection_class, getExtensionName)
5143 {
5144 reflection_object *intern;
5145 zend_class_entry *ce;
5146
5147 if (zend_parse_parameters_none() == FAILURE) {
5148 return;
5149 }
5150
5151 GET_REFLECTION_OBJECT_PTR(ce);
5152
5153 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5154 RETURN_STRING(ce->info.internal.module->name);
5155 } else {
5156 RETURN_FALSE;
5157 }
5158 }
5159 /* }}} */
5160
5161 /* {{{ proto public bool ReflectionClass::inNamespace()
5162 Returns whether this class is defined in namespace */
ZEND_METHOD(reflection_class,inNamespace)5163 ZEND_METHOD(reflection_class, inNamespace)
5164 {
5165 zval *name;
5166 const char *backslash;
5167
5168 if (zend_parse_parameters_none() == FAILURE) {
5169 return;
5170 }
5171 if ((name = _default_load_name(getThis())) == NULL) {
5172 RETURN_FALSE;
5173 }
5174 if (Z_TYPE_P(name) == IS_STRING
5175 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5176 && backslash > Z_STRVAL_P(name))
5177 {
5178 RETURN_TRUE;
5179 }
5180 RETURN_FALSE;
5181 }
5182 /* }}} */
5183
5184 /* {{{ proto public string ReflectionClass::getNamespaceName()
5185 Returns the name of namespace where this class is defined */
ZEND_METHOD(reflection_class,getNamespaceName)5186 ZEND_METHOD(reflection_class, getNamespaceName)
5187 {
5188 zval *name;
5189 const char *backslash;
5190
5191 if (zend_parse_parameters_none() == FAILURE) {
5192 return;
5193 }
5194 if ((name = _default_load_name(getThis())) == NULL) {
5195 RETURN_FALSE;
5196 }
5197 if (Z_TYPE_P(name) == IS_STRING
5198 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5199 && backslash > Z_STRVAL_P(name))
5200 {
5201 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
5202 }
5203 RETURN_EMPTY_STRING();
5204 }
5205 /* }}} */
5206
5207 /* {{{ proto public string ReflectionClass::getShortName()
5208 Returns the short name of the class (without namespace part) */
ZEND_METHOD(reflection_class,getShortName)5209 ZEND_METHOD(reflection_class, getShortName)
5210 {
5211 zval *name;
5212 const char *backslash;
5213
5214 if (zend_parse_parameters_none() == FAILURE) {
5215 return;
5216 }
5217 if ((name = _default_load_name(getThis())) == NULL) {
5218 RETURN_FALSE;
5219 }
5220 if (Z_TYPE_P(name) == IS_STRING
5221 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5222 && backslash > Z_STRVAL_P(name))
5223 {
5224 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
5225 }
5226 ZVAL_COPY_DEREF(return_value, name);
5227 }
5228 /* }}} */
5229
5230 /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
5231 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_object,export)5232 ZEND_METHOD(reflection_object, export)
5233 {
5234 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
5235 }
5236 /* }}} */
5237
5238 /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
5239 Constructor. Takes an instance as an argument */
ZEND_METHOD(reflection_object,__construct)5240 ZEND_METHOD(reflection_object, __construct)
5241 {
5242 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5243 }
5244 /* }}} */
5245
5246 /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
5247 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_property,export)5248 ZEND_METHOD(reflection_property, export)
5249 {
5250 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
5251 }
5252 /* }}} */
5253
5254 /* {{{ proto public static mixed ReflectionClassConstant::export(mixed class, string name [, bool return]) throws ReflectionException
5255 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class_constant,export)5256 ZEND_METHOD(reflection_class_constant, export)
5257 {
5258 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_constant_ptr, 2);
5259 }
5260 /* }}} */
5261
5262 /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
5263 Constructor. Throws an Exception in case the given property does not exist */
ZEND_METHOD(reflection_property,__construct)5264 ZEND_METHOD(reflection_property, __construct)
5265 {
5266 zval propname, cname, *classname;
5267 zend_string *name;
5268 int dynam_prop = 0;
5269 zval *object;
5270 reflection_object *intern;
5271 zend_class_entry *ce;
5272 zend_property_info *property_info = NULL;
5273 property_reference *reference;
5274
5275 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &name) == FAILURE) {
5276 return;
5277 }
5278
5279 object = getThis();
5280 intern = Z_REFLECTION_P(object);
5281
5282 /* Find the class entry */
5283 switch (Z_TYPE_P(classname)) {
5284 case IS_STRING:
5285 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
5286 zend_throw_exception_ex(reflection_exception_ptr, 0,
5287 "Class %s does not exist", Z_STRVAL_P(classname));
5288 return;
5289 }
5290 break;
5291
5292 case IS_OBJECT:
5293 ce = Z_OBJCE_P(classname);
5294 break;
5295
5296 default:
5297 _DO_THROW("The parameter class is expected to be either a string or an object");
5298 /* returns out of this function */
5299 }
5300
5301 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) == NULL || (property_info->flags & ZEND_ACC_SHADOW)) {
5302 /* Check for dynamic properties */
5303 if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
5304 if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname), name)) {
5305 dynam_prop = 1;
5306 }
5307 }
5308 if (dynam_prop == 0) {
5309 zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
5310 return;
5311 }
5312 }
5313
5314 if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
5315 /* we have to search the class hierarchy for this (implicit) public or protected property */
5316 zend_class_entry *tmp_ce = ce;
5317 zend_property_info *tmp_info;
5318
5319 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
5320 ce = tmp_ce;
5321 property_info = tmp_info;
5322 tmp_ce = tmp_ce->parent;
5323 }
5324 }
5325
5326 if (dynam_prop == 0) {
5327 ZVAL_STR_COPY(&cname, property_info->ce->name);
5328 } else {
5329 ZVAL_STR_COPY(&cname, ce->name);
5330 }
5331 reflection_update_property_class(object, &cname);
5332
5333 ZVAL_STR_COPY(&propname, name);
5334 reflection_update_property_name(object, &propname);
5335
5336 reference = (property_reference*) emalloc(sizeof(property_reference));
5337 if (dynam_prop) {
5338 reference->prop.flags = ZEND_ACC_IMPLICIT_PUBLIC;
5339 reference->prop.name = name;
5340 reference->prop.doc_comment = NULL;
5341 reference->prop.ce = ce;
5342 } else {
5343 reference->prop = *property_info;
5344 }
5345 reference->ce = ce;
5346 reference->unmangled_name = zend_string_copy(name);
5347 intern->ptr = reference;
5348 intern->ref_type = REF_TYPE_PROPERTY;
5349 intern->ce = ce;
5350 intern->ignore_visibility = 0;
5351 }
5352 /* }}} */
5353
5354 /* {{{ proto public string ReflectionProperty::__toString()
5355 Returns a string representation */
ZEND_METHOD(reflection_property,__toString)5356 ZEND_METHOD(reflection_property, __toString)
5357 {
5358 reflection_object *intern;
5359 property_reference *ref;
5360 smart_str str = {0};
5361
5362 if (zend_parse_parameters_none() == FAILURE) {
5363 return;
5364 }
5365 GET_REFLECTION_OBJECT_PTR(ref);
5366 _property_string(&str, &ref->prop, ZSTR_VAL(ref->unmangled_name), "");
5367 RETURN_STR(smart_str_extract(&str));
5368 }
5369 /* }}} */
5370
5371 /* {{{ proto public string ReflectionProperty::getName()
5372 Returns the class' name */
ZEND_METHOD(reflection_property,getName)5373 ZEND_METHOD(reflection_property, getName)
5374 {
5375 if (zend_parse_parameters_none() == FAILURE) {
5376 return;
5377 }
5378 _default_get_name(getThis(), return_value);
5379 }
5380 /* }}} */
5381
_property_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)5382 static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
5383 {
5384 reflection_object *intern;
5385 property_reference *ref;
5386
5387 if (zend_parse_parameters_none() == FAILURE) {
5388 return;
5389 }
5390 GET_REFLECTION_OBJECT_PTR(ref);
5391 RETURN_BOOL(ref->prop.flags & mask);
5392 }
5393 /* }}} */
5394
5395 /* {{{ proto public bool ReflectionProperty::isPublic()
5396 Returns whether this property is public */
ZEND_METHOD(reflection_property,isPublic)5397 ZEND_METHOD(reflection_property, isPublic)
5398 {
5399 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
5400 }
5401 /* }}} */
5402
5403 /* {{{ proto public bool ReflectionProperty::isPrivate()
5404 Returns whether this property is private */
ZEND_METHOD(reflection_property,isPrivate)5405 ZEND_METHOD(reflection_property, isPrivate)
5406 {
5407 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
5408 }
5409 /* }}} */
5410
5411 /* {{{ proto public bool ReflectionProperty::isProtected()
5412 Returns whether this property is protected */
ZEND_METHOD(reflection_property,isProtected)5413 ZEND_METHOD(reflection_property, isProtected)
5414 {
5415 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
5416 }
5417 /* }}} */
5418
5419 /* {{{ proto public bool ReflectionProperty::isStatic()
5420 Returns whether this property is static */
ZEND_METHOD(reflection_property,isStatic)5421 ZEND_METHOD(reflection_property, isStatic)
5422 {
5423 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
5424 }
5425 /* }}} */
5426
5427 /* {{{ proto public bool ReflectionProperty::isDefault()
5428 Returns whether this property is default (declared at compilation time). */
ZEND_METHOD(reflection_property,isDefault)5429 ZEND_METHOD(reflection_property, isDefault)
5430 {
5431 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ~ZEND_ACC_IMPLICIT_PUBLIC);
5432 }
5433 /* }}} */
5434
5435 /* {{{ proto public int ReflectionProperty::getModifiers()
5436 Returns a bitfield of the access modifiers for this property */
ZEND_METHOD(reflection_property,getModifiers)5437 ZEND_METHOD(reflection_property, getModifiers)
5438 {
5439 reflection_object *intern;
5440 property_reference *ref;
5441 uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_IMPLICIT_PUBLIC | ZEND_ACC_STATIC;
5442
5443 if (zend_parse_parameters_none() == FAILURE) {
5444 return;
5445 }
5446 GET_REFLECTION_OBJECT_PTR(ref);
5447
5448 RETURN_LONG((ref->prop.flags & keep_flags));
5449 }
5450 /* }}} */
5451
5452 /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
5453 Returns this property's value */
ZEND_METHOD(reflection_property,getValue)5454 ZEND_METHOD(reflection_property, getValue)
5455 {
5456 reflection_object *intern;
5457 property_reference *ref;
5458 zval *object, *name;
5459 zval *member_p = NULL;
5460
5461 GET_REFLECTION_OBJECT_PTR(ref);
5462
5463 if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
5464 name = _default_load_name(getThis());
5465 zend_throw_exception_ex(reflection_exception_ptr, 0,
5466 "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5467 return;
5468 }
5469
5470 if (ref->prop.flags & ZEND_ACC_STATIC) {
5471 member_p = zend_read_static_property_ex(ref->ce, ref->unmangled_name, 0);
5472 if (member_p) {
5473 ZVAL_COPY_DEREF(return_value, member_p);
5474 }
5475 } else {
5476 zval rv;
5477
5478 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5479 return;
5480 }
5481
5482 if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5483 _DO_THROW("Given object is not an instance of the class this property was declared in");
5484 /* Returns from this function */
5485 }
5486
5487 member_p = zend_read_property_ex(ref->ce, object, ref->unmangled_name, 0, &rv);
5488 if (member_p != &rv) {
5489 ZVAL_COPY_DEREF(return_value, member_p);
5490 } else {
5491 if (Z_ISREF_P(member_p)) {
5492 zend_unwrap_reference(member_p);
5493 }
5494 ZVAL_COPY_VALUE(return_value, member_p);
5495 }
5496 }
5497 }
5498 /* }}} */
5499
5500 /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
5501 Sets this property's value */
ZEND_METHOD(reflection_property,setValue)5502 ZEND_METHOD(reflection_property, setValue)
5503 {
5504 reflection_object *intern;
5505 property_reference *ref;
5506 zval *object, *name;
5507 zval *value;
5508 zval *tmp;
5509
5510 GET_REFLECTION_OBJECT_PTR(ref);
5511
5512 if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5513 name = _default_load_name(getThis());
5514 zend_throw_exception_ex(reflection_exception_ptr, 0,
5515 "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5516 return;
5517 }
5518
5519 if (ref->prop.flags & ZEND_ACC_STATIC) {
5520 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
5521 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
5522 return;
5523 }
5524 }
5525
5526 zend_update_static_property_ex(ref->ce, ref->unmangled_name, value);
5527 } else {
5528 if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
5529 return;
5530 }
5531
5532 zend_update_property_ex(ref->ce, object, ref->unmangled_name, value);
5533 }
5534 }
5535 /* }}} */
5536
5537 /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
5538 Get the declaring class */
ZEND_METHOD(reflection_property,getDeclaringClass)5539 ZEND_METHOD(reflection_property, getDeclaringClass)
5540 {
5541 reflection_object *intern;
5542 property_reference *ref;
5543 zend_class_entry *tmp_ce, *ce;
5544 zend_property_info *tmp_info;
5545
5546 if (zend_parse_parameters_none() == FAILURE) {
5547 return;
5548 }
5549 GET_REFLECTION_OBJECT_PTR(ref);
5550
5551 ce = tmp_ce = ref->ce;
5552 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, ref->unmangled_name)) != NULL) {
5553 if (tmp_info->flags & ZEND_ACC_PRIVATE || tmp_info->flags & ZEND_ACC_SHADOW) {
5554 /* it's a private property, so it can't be inherited */
5555 break;
5556 }
5557 ce = tmp_ce;
5558 if (tmp_ce == tmp_info->ce) {
5559 /* declared in this class, done */
5560 break;
5561 }
5562 tmp_ce = tmp_ce->parent;
5563 }
5564
5565 zend_reflection_class_factory(ce, return_value);
5566 }
5567 /* }}} */
5568
5569 /* {{{ proto public string ReflectionProperty::getDocComment()
5570 Returns the doc comment for this property */
ZEND_METHOD(reflection_property,getDocComment)5571 ZEND_METHOD(reflection_property, getDocComment)
5572 {
5573 reflection_object *intern;
5574 property_reference *ref;
5575
5576 if (zend_parse_parameters_none() == FAILURE) {
5577 return;
5578 }
5579 GET_REFLECTION_OBJECT_PTR(ref);
5580 if (ref->prop.doc_comment) {
5581 RETURN_STR_COPY(ref->prop.doc_comment);
5582 }
5583 RETURN_FALSE;
5584 }
5585 /* }}} */
5586
5587 /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
5588 Sets whether non-public properties can be requested */
ZEND_METHOD(reflection_property,setAccessible)5589 ZEND_METHOD(reflection_property, setAccessible)
5590 {
5591 reflection_object *intern;
5592 zend_bool visible;
5593
5594 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
5595 return;
5596 }
5597
5598 intern = Z_REFLECTION_P(getThis());
5599
5600 intern->ignore_visibility = visible;
5601 }
5602 /* }}} */
5603
5604 /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
5605 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_extension,export)5606 ZEND_METHOD(reflection_extension, export)
5607 {
5608 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
5609 }
5610 /* }}} */
5611
5612 /* {{{ proto public void ReflectionExtension::__construct(string name)
5613 Constructor. Throws an Exception in case the given extension does not exist */
ZEND_METHOD(reflection_extension,__construct)5614 ZEND_METHOD(reflection_extension, __construct)
5615 {
5616 zval name;
5617 zval *object;
5618 char *lcname;
5619 reflection_object *intern;
5620 zend_module_entry *module;
5621 char *name_str;
5622 size_t name_len;
5623 ALLOCA_FLAG(use_heap)
5624
5625 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5626 return;
5627 }
5628
5629 object = getThis();
5630 intern = Z_REFLECTION_P(object);
5631 lcname = do_alloca(name_len + 1, use_heap);
5632 zend_str_tolower_copy(lcname, name_str, name_len);
5633 if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
5634 free_alloca(lcname, use_heap);
5635 zend_throw_exception_ex(reflection_exception_ptr, 0,
5636 "Extension %s does not exist", name_str);
5637 return;
5638 }
5639 free_alloca(lcname, use_heap);
5640 ZVAL_STRING(&name, module->name);
5641 reflection_update_property_name(object, &name);
5642 intern->ptr = module;
5643 intern->ref_type = REF_TYPE_OTHER;
5644 intern->ce = NULL;
5645 }
5646 /* }}} */
5647
5648 /* {{{ proto public string ReflectionExtension::__toString()
5649 Returns a string representation */
ZEND_METHOD(reflection_extension,__toString)5650 ZEND_METHOD(reflection_extension, __toString)
5651 {
5652 reflection_object *intern;
5653 zend_module_entry *module;
5654 smart_str str = {0};
5655
5656 if (zend_parse_parameters_none() == FAILURE) {
5657 return;
5658 }
5659 GET_REFLECTION_OBJECT_PTR(module);
5660 _extension_string(&str, module, "");
5661 RETURN_STR(smart_str_extract(&str));
5662 }
5663 /* }}} */
5664
5665 /* {{{ proto public string ReflectionExtension::getName()
5666 Returns this extension's name */
ZEND_METHOD(reflection_extension,getName)5667 ZEND_METHOD(reflection_extension, getName)
5668 {
5669 if (zend_parse_parameters_none() == FAILURE) {
5670 return;
5671 }
5672 _default_get_name(getThis(), return_value);
5673 }
5674 /* }}} */
5675
5676 /* {{{ proto public string ReflectionExtension::getVersion()
5677 Returns this extension's version */
ZEND_METHOD(reflection_extension,getVersion)5678 ZEND_METHOD(reflection_extension, getVersion)
5679 {
5680 reflection_object *intern;
5681 zend_module_entry *module;
5682
5683 if (zend_parse_parameters_none() == FAILURE) {
5684 return;
5685 }
5686 GET_REFLECTION_OBJECT_PTR(module);
5687
5688 /* An extension does not necessarily have a version number */
5689 if (module->version == NO_VERSION_YET) {
5690 RETURN_NULL();
5691 } else {
5692 RETURN_STRING(module->version);
5693 }
5694 }
5695 /* }}} */
5696
5697 /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
5698 Returns an array of this extension's functions */
ZEND_METHOD(reflection_extension,getFunctions)5699 ZEND_METHOD(reflection_extension, getFunctions)
5700 {
5701 reflection_object *intern;
5702 zend_module_entry *module;
5703 zval function;
5704 zend_function *fptr;
5705
5706 if (zend_parse_parameters_none() == FAILURE) {
5707 return;
5708 }
5709 GET_REFLECTION_OBJECT_PTR(module);
5710
5711 array_init(return_value);
5712 ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
5713 if (fptr->common.type==ZEND_INTERNAL_FUNCTION
5714 && fptr->internal_function.module == module) {
5715 reflection_function_factory(fptr, NULL, &function);
5716 zend_hash_update(Z_ARRVAL_P(return_value), fptr->common.function_name, &function);
5717 }
5718 } ZEND_HASH_FOREACH_END();
5719 }
5720 /* }}} */
5721
_addconstant(zval * el,int num_args,va_list args,zend_hash_key * hash_key)5722 static int _addconstant(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
5723 {
5724 zval const_val;
5725 zend_constant *constant = (zend_constant*)Z_PTR_P(el);
5726 zval *retval = va_arg(args, zval*);
5727 int number = va_arg(args, int);
5728
5729 if (number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
5730 ZVAL_COPY_OR_DUP(&const_val, &constant->value);
5731 zend_hash_update(Z_ARRVAL_P(retval), constant->name, &const_val);
5732 }
5733 return 0;
5734 }
5735 /* }}} */
5736
5737 /* {{{ proto public array ReflectionExtension::getConstants()
5738 Returns an associative array containing this extension's constants and their values */
ZEND_METHOD(reflection_extension,getConstants)5739 ZEND_METHOD(reflection_extension, getConstants)
5740 {
5741 reflection_object *intern;
5742 zend_module_entry *module;
5743
5744 if (zend_parse_parameters_none() == FAILURE) {
5745 return;
5746 }
5747 GET_REFLECTION_OBJECT_PTR(module);
5748
5749 array_init(return_value);
5750 zend_hash_apply_with_arguments(EG(zend_constants), (apply_func_args_t) _addconstant, 2, return_value, module->module_number);
5751 }
5752 /* }}} */
5753
5754 /* {{{ _addinientry */
_addinientry(zval * el,int num_args,va_list args,zend_hash_key * hash_key)5755 static int _addinientry(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
5756 {
5757 zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
5758 zval *retval = va_arg(args, zval*);
5759 int number = va_arg(args, int);
5760
5761 if (number == ini_entry->module_number) {
5762 if (ini_entry->value) {
5763 zval zv;
5764
5765 ZVAL_STR_COPY(&zv, ini_entry->value);
5766 zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
5767 } else {
5768 zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &EG(uninitialized_zval));
5769 }
5770 }
5771 return ZEND_HASH_APPLY_KEEP;
5772 }
5773 /* }}} */
5774
5775 /* {{{ proto public array ReflectionExtension::getINIEntries()
5776 Returns an associative array containing this extension's INI entries and their values */
ZEND_METHOD(reflection_extension,getINIEntries)5777 ZEND_METHOD(reflection_extension, getINIEntries)
5778 {
5779 reflection_object *intern;
5780 zend_module_entry *module;
5781
5782 if (zend_parse_parameters_none() == FAILURE) {
5783 return;
5784 }
5785 GET_REFLECTION_OBJECT_PTR(module);
5786
5787 array_init(return_value);
5788 zend_hash_apply_with_arguments(EG(ini_directives), (apply_func_args_t) _addinientry, 2, return_value, module->module_number);
5789 }
5790 /* }}} */
5791
5792 /* {{{ add_extension_class */
add_extension_class(zval * zv,int num_args,va_list args,zend_hash_key * hash_key)5793 static int add_extension_class(zval *zv, int num_args, va_list args, zend_hash_key *hash_key)
5794 {
5795 zend_class_entry *ce = Z_PTR_P(zv);
5796 zval *class_array = va_arg(args, zval*), zclass;
5797 struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
5798 int add_reflection_class = va_arg(args, int);
5799
5800 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
5801 zend_string *name;
5802
5803 if (zend_binary_strcasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key))) {
5804 /* This is an class alias, use alias name */
5805 name = hash_key->key;
5806 } else {
5807 /* Use class name */
5808 name = ce->name;
5809 }
5810 if (add_reflection_class) {
5811 zend_reflection_class_factory(ce, &zclass);
5812 zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
5813 } else {
5814 add_next_index_str(class_array, zend_string_copy(name));
5815 }
5816 }
5817 return ZEND_HASH_APPLY_KEEP;
5818 }
5819 /* }}} */
5820
5821 /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
5822 Returns an array containing ReflectionClass objects for all classes of this extension */
ZEND_METHOD(reflection_extension,getClasses)5823 ZEND_METHOD(reflection_extension, getClasses)
5824 {
5825 reflection_object *intern;
5826 zend_module_entry *module;
5827
5828 if (zend_parse_parameters_none() == FAILURE) {
5829 return;
5830 }
5831 GET_REFLECTION_OBJECT_PTR(module);
5832
5833 array_init(return_value);
5834 zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) add_extension_class, 3, return_value, module, 1);
5835 }
5836 /* }}} */
5837
5838 /* {{{ proto public array ReflectionExtension::getClassNames()
5839 Returns an array containing all names of all classes of this extension */
ZEND_METHOD(reflection_extension,getClassNames)5840 ZEND_METHOD(reflection_extension, getClassNames)
5841 {
5842 reflection_object *intern;
5843 zend_module_entry *module;
5844
5845 if (zend_parse_parameters_none() == FAILURE) {
5846 return;
5847 }
5848 GET_REFLECTION_OBJECT_PTR(module);
5849
5850 array_init(return_value);
5851 zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) add_extension_class, 3, return_value, module, 0);
5852 }
5853 /* }}} */
5854
5855 /* {{{ proto public array ReflectionExtension::getDependencies()
5856 Returns an array containing all names of all extensions this extension depends on */
ZEND_METHOD(reflection_extension,getDependencies)5857 ZEND_METHOD(reflection_extension, getDependencies)
5858 {
5859 reflection_object *intern;
5860 zend_module_entry *module;
5861 const zend_module_dep *dep;
5862
5863 if (zend_parse_parameters_none() == FAILURE) {
5864 return;
5865 }
5866 GET_REFLECTION_OBJECT_PTR(module);
5867
5868 dep = module->deps;
5869
5870 if (!dep)
5871 {
5872 ZVAL_EMPTY_ARRAY(return_value);
5873 return;
5874 }
5875
5876 array_init(return_value);
5877 while(dep->name) {
5878 zend_string *relation;
5879 char *rel_type;
5880 size_t len = 0;
5881
5882 switch(dep->type) {
5883 case MODULE_DEP_REQUIRED:
5884 rel_type = "Required";
5885 len += sizeof("Required") - 1;
5886 break;
5887 case MODULE_DEP_CONFLICTS:
5888 rel_type = "Conflicts";
5889 len += sizeof("Conflicts") - 1;
5890 break;
5891 case MODULE_DEP_OPTIONAL:
5892 rel_type = "Optional";
5893 len += sizeof("Optional") - 1;
5894 break;
5895 default:
5896 rel_type = "Error"; /* shouldn't happen */
5897 len += sizeof("Error") - 1;
5898 break;
5899 }
5900
5901 if (dep->rel) {
5902 len += strlen(dep->rel) + 1;
5903 }
5904
5905 if (dep->version) {
5906 len += strlen(dep->version) + 1;
5907 }
5908
5909 relation = zend_string_alloc(len, 0);
5910 snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
5911 rel_type,
5912 dep->rel ? " " : "",
5913 dep->rel ? dep->rel : "",
5914 dep->version ? " " : "",
5915 dep->version ? dep->version : "");
5916 add_assoc_str(return_value, dep->name, relation);
5917 dep++;
5918 }
5919 }
5920 /* }}} */
5921
5922 /* {{{ proto public void ReflectionExtension::info()
5923 Prints phpinfo block for the extension */
ZEND_METHOD(reflection_extension,info)5924 ZEND_METHOD(reflection_extension, info)
5925 {
5926 reflection_object *intern;
5927 zend_module_entry *module;
5928
5929 if (zend_parse_parameters_none() == FAILURE) {
5930 return;
5931 }
5932 GET_REFLECTION_OBJECT_PTR(module);
5933
5934 php_info_print_module(module);
5935 }
5936 /* }}} */
5937
5938 /* {{{ proto public bool ReflectionExtension::isPersistent()
5939 Returns whether this extension is persistent */
ZEND_METHOD(reflection_extension,isPersistent)5940 ZEND_METHOD(reflection_extension, isPersistent)
5941 {
5942 reflection_object *intern;
5943 zend_module_entry *module;
5944
5945 if (zend_parse_parameters_none() == FAILURE) {
5946 return;
5947 }
5948 GET_REFLECTION_OBJECT_PTR(module);
5949
5950 RETURN_BOOL(module->type == MODULE_PERSISTENT);
5951 }
5952 /* }}} */
5953
5954 /* {{{ proto public bool ReflectionExtension::isTemporary()
5955 Returns whether this extension is temporary */
ZEND_METHOD(reflection_extension,isTemporary)5956 ZEND_METHOD(reflection_extension, isTemporary)
5957 {
5958 reflection_object *intern;
5959 zend_module_entry *module;
5960
5961 if (zend_parse_parameters_none() == FAILURE) {
5962 return;
5963 }
5964 GET_REFLECTION_OBJECT_PTR(module);
5965
5966 RETURN_BOOL(module->type == MODULE_TEMPORARY);
5967 }
5968 /* }}} */
5969
5970 /* {{{ proto public static mixed ReflectionZendExtension::export(string name [, bool return]) throws ReflectionException
5971 * Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_zend_extension,export)5972 ZEND_METHOD(reflection_zend_extension, export)
5973 {
5974 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
5975 }
5976 /* }}} */
5977
5978 /* {{{ proto public void ReflectionZendExtension::__construct(string name)
5979 Constructor. Throws an Exception in case the given Zend extension does not exist */
ZEND_METHOD(reflection_zend_extension,__construct)5980 ZEND_METHOD(reflection_zend_extension, __construct)
5981 {
5982 zval name;
5983 zval *object;
5984 reflection_object *intern;
5985 zend_extension *extension;
5986 char *name_str;
5987 size_t name_len;
5988
5989 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5990 return;
5991 }
5992
5993 object = getThis();
5994 intern = Z_REFLECTION_P(object);
5995
5996 extension = zend_get_extension(name_str);
5997 if (!extension) {
5998 zend_throw_exception_ex(reflection_exception_ptr, 0,
5999 "Zend Extension %s does not exist", name_str);
6000 return;
6001 }
6002 ZVAL_STRING(&name, extension->name);
6003 reflection_update_property_name(object, &name);
6004 intern->ptr = extension;
6005 intern->ref_type = REF_TYPE_OTHER;
6006 intern->ce = NULL;
6007 }
6008 /* }}} */
6009
6010 /* {{{ proto public string ReflectionZendExtension::__toString()
6011 Returns a string representation */
ZEND_METHOD(reflection_zend_extension,__toString)6012 ZEND_METHOD(reflection_zend_extension, __toString)
6013 {
6014 reflection_object *intern;
6015 zend_extension *extension;
6016 smart_str str = {0};
6017
6018 if (zend_parse_parameters_none() == FAILURE) {
6019 return;
6020 }
6021 GET_REFLECTION_OBJECT_PTR(extension);
6022 _zend_extension_string(&str, extension, "");
6023 RETURN_STR(smart_str_extract(&str));
6024 }
6025 /* }}} */
6026
6027 /* {{{ proto public string ReflectionZendExtension::getName()
6028 Returns the name of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getName)6029 ZEND_METHOD(reflection_zend_extension, getName)
6030 {
6031 reflection_object *intern;
6032 zend_extension *extension;
6033
6034 if (zend_parse_parameters_none() == FAILURE) {
6035 return;
6036 }
6037 GET_REFLECTION_OBJECT_PTR(extension);
6038
6039 RETURN_STRING(extension->name);
6040 }
6041 /* }}} */
6042
6043 /* {{{ proto public string ReflectionZendExtension::getVersion()
6044 Returns the version information of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getVersion)6045 ZEND_METHOD(reflection_zend_extension, getVersion)
6046 {
6047 reflection_object *intern;
6048 zend_extension *extension;
6049
6050 if (zend_parse_parameters_none() == FAILURE) {
6051 return;
6052 }
6053 GET_REFLECTION_OBJECT_PTR(extension);
6054
6055 if (extension->version) {
6056 RETURN_STRING(extension->version);
6057 } else {
6058 RETURN_EMPTY_STRING();
6059 }
6060 }
6061 /* }}} */
6062
6063 /* {{{ proto public void ReflectionZendExtension::getAuthor()
6064 * Returns the name of this Zend extension's author */
ZEND_METHOD(reflection_zend_extension,getAuthor)6065 ZEND_METHOD(reflection_zend_extension, getAuthor)
6066 {
6067 reflection_object *intern;
6068 zend_extension *extension;
6069
6070 if (zend_parse_parameters_none() == FAILURE) {
6071 return;
6072 }
6073 GET_REFLECTION_OBJECT_PTR(extension);
6074
6075 if (extension->author) {
6076 RETURN_STRING(extension->author);
6077 } else {
6078 RETURN_EMPTY_STRING();
6079 }
6080 }
6081 /* }}} */
6082
6083 /* {{{ proto public void ReflectionZendExtension::getURL()
6084 Returns this Zend extension's URL*/
ZEND_METHOD(reflection_zend_extension,getURL)6085 ZEND_METHOD(reflection_zend_extension, getURL)
6086 {
6087 reflection_object *intern;
6088 zend_extension *extension;
6089
6090 if (zend_parse_parameters_none() == FAILURE) {
6091 return;
6092 }
6093 GET_REFLECTION_OBJECT_PTR(extension);
6094
6095 if (extension->URL) {
6096 RETURN_STRING(extension->URL);
6097 } else {
6098 RETURN_EMPTY_STRING();
6099 }
6100 }
6101 /* }}} */
6102
6103 /* {{{ proto public void ReflectionZendExtension::getCopyright()
6104 Returns this Zend extension's copyright information */
ZEND_METHOD(reflection_zend_extension,getCopyright)6105 ZEND_METHOD(reflection_zend_extension, getCopyright)
6106 {
6107 reflection_object *intern;
6108 zend_extension *extension;
6109
6110 if (zend_parse_parameters_none() == FAILURE) {
6111 return;
6112 }
6113 GET_REFLECTION_OBJECT_PTR(extension);
6114
6115 if (extension->copyright) {
6116 RETURN_STRING(extension->copyright);
6117 } else {
6118 RETURN_EMPTY_STRING();
6119 }
6120 }
6121 /* }}} */
6122
6123 /* {{{ method tables */
6124 static const zend_function_entry reflection_exception_functions[] = {
6125 PHP_FE_END
6126 };
6127
6128 ZEND_BEGIN_ARG_INFO(arginfo_reflection__void, 0)
6129 ZEND_END_ARG_INFO()
6130
6131
6132 ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
6133 ZEND_ARG_INFO(0, modifiers)
6134 ZEND_END_ARG_INFO()
6135
6136 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
6137 ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
6138 ZEND_ARG_INFO(0, return)
6139 ZEND_END_ARG_INFO()
6140
6141 static const zend_function_entry reflection_functions[] = {
6142 ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6143 ZEND_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6144 PHP_FE_END
6145 };
6146
6147 static const zend_function_entry reflector_functions[] = {
6148 ZEND_FENTRY(export, NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)
6149 ZEND_ABSTRACT_ME(reflector, __toString, arginfo_reflection__void)
6150 PHP_FE_END
6151 };
6152
6153 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
6154 ZEND_ARG_INFO(0, name)
6155 ZEND_ARG_INFO(0, return)
6156 ZEND_END_ARG_INFO()
6157
6158 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
6159 ZEND_ARG_INFO(0, name)
6160 ZEND_END_ARG_INFO()
6161
6162 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
6163 ZEND_ARG_INFO(0, args)
6164 ZEND_END_ARG_INFO()
6165
6166 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
6167 ZEND_ARG_ARRAY_INFO(0, args, 0)
6168 ZEND_END_ARG_INFO()
6169
6170 static const zend_function_entry reflection_function_abstract_functions[] = {
6171 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6172 ZEND_ME(reflection_function, inNamespace, arginfo_reflection__void, 0)
6173 ZEND_ME(reflection_function, isClosure, arginfo_reflection__void, 0)
6174 ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
6175 ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
6176 ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
6177 ZEND_ME(reflection_function, isGenerator, arginfo_reflection__void, 0)
6178 ZEND_ME(reflection_function, isVariadic, arginfo_reflection__void, 0)
6179 ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
6180 ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
6181 ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
6182 ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
6183 ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
6184 ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
6185 ZEND_ME(reflection_function, getFileName, arginfo_reflection__void, 0)
6186 ZEND_ME(reflection_function, getName, arginfo_reflection__void, 0)
6187 ZEND_ME(reflection_function, getNamespaceName, arginfo_reflection__void, 0)
6188 ZEND_ME(reflection_function, getNumberOfParameters, arginfo_reflection__void, 0)
6189 ZEND_ME(reflection_function, getNumberOfRequiredParameters, arginfo_reflection__void, 0)
6190 ZEND_ME(reflection_function, getParameters, arginfo_reflection__void, 0)
6191 ZEND_ME(reflection_function, getShortName, arginfo_reflection__void, 0)
6192 ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
6193 ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
6194 ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
6195 ZEND_ME(reflection_function, hasReturnType, arginfo_reflection__void, 0)
6196 ZEND_ME(reflection_function, getReturnType, arginfo_reflection__void, 0)
6197 PHP_FE_END
6198 };
6199
6200 static const zend_function_entry reflection_function_functions[] = {
6201 ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
6202 ZEND_ME(reflection_function, __toString, arginfo_reflection__void, 0)
6203 ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6204 ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
6205 ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
6206 ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
6207 ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
6208 PHP_FE_END
6209 };
6210
6211 ZEND_BEGIN_ARG_INFO(arginfo_reflection_generator___construct, 0)
6212 ZEND_ARG_INFO(0, generator)
6213 ZEND_END_ARG_INFO()
6214
6215 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_generator_trace, 0, 0, 0)
6216 ZEND_ARG_INFO(0, options)
6217 ZEND_END_ARG_INFO()
6218
6219 static const zend_function_entry reflection_generator_functions[] = {
6220 ZEND_ME(reflection_generator, __construct, arginfo_reflection_generator___construct, 0)
6221 ZEND_ME(reflection_generator, getExecutingLine, arginfo_reflection__void, 0)
6222 ZEND_ME(reflection_generator, getExecutingFile, arginfo_reflection__void, 0)
6223 ZEND_ME(reflection_generator, getTrace, arginfo_reflection_generator_trace, 0)
6224 ZEND_ME(reflection_generator, getFunction, arginfo_reflection__void, 0)
6225 ZEND_ME(reflection_generator, getThis, arginfo_reflection__void, 0)
6226 ZEND_ME(reflection_generator, getExecutingGenerator, arginfo_reflection__void, 0)
6227 PHP_FE_END
6228 };
6229
6230 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
6231 ZEND_ARG_INFO(0, class)
6232 ZEND_ARG_INFO(0, name)
6233 ZEND_ARG_INFO(0, return)
6234 ZEND_END_ARG_INFO()
6235
6236 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
6237 ZEND_ARG_INFO(0, class_or_method)
6238 ZEND_ARG_INFO(0, name)
6239 ZEND_END_ARG_INFO()
6240
6241 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
6242 ZEND_ARG_INFO(0, object)
6243 ZEND_ARG_INFO(0, args)
6244 ZEND_END_ARG_INFO()
6245
6246 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
6247 ZEND_ARG_INFO(0, object)
6248 ZEND_ARG_ARRAY_INFO(0, args, 0)
6249 ZEND_END_ARG_INFO()
6250
6251 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
6252 ZEND_ARG_INFO(0, value)
6253 ZEND_END_ARG_INFO()
6254
6255 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0)
6256 ZEND_ARG_INFO(0, object)
6257 ZEND_END_ARG_INFO()
6258
6259 static const zend_function_entry reflection_method_functions[] = {
6260 ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6261 ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
6262 ZEND_ME(reflection_method, __toString, arginfo_reflection__void, 0)
6263 ZEND_ME(reflection_method, isPublic, arginfo_reflection__void, 0)
6264 ZEND_ME(reflection_method, isPrivate, arginfo_reflection__void, 0)
6265 ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0)
6266 ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0)
6267 ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0)
6268 ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
6269 ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
6270 ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
6271 ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
6272 ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
6273 ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
6274 ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
6275 ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
6276 ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
6277 ZEND_ME(reflection_method, setAccessible, arginfo_reflection_method_setAccessible, 0)
6278 PHP_FE_END
6279 };
6280
6281
6282 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
6283 ZEND_ARG_INFO(0, argument)
6284 ZEND_ARG_INFO(0, return)
6285 ZEND_END_ARG_INFO()
6286
6287 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
6288 ZEND_ARG_INFO(0, argument)
6289 ZEND_END_ARG_INFO()
6290
6291 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
6292 ZEND_ARG_INFO(0, name)
6293 ZEND_ARG_INFO(0, default)
6294 ZEND_END_ARG_INFO()
6295
6296 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
6297 ZEND_ARG_INFO(0, name)
6298 ZEND_ARG_INFO(0, value)
6299 ZEND_END_ARG_INFO()
6300
6301 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
6302 ZEND_ARG_INFO(0, name)
6303 ZEND_END_ARG_INFO()
6304
6305 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
6306 ZEND_ARG_INFO(0, name)
6307 ZEND_END_ARG_INFO()
6308
6309 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
6310 ZEND_ARG_INFO(0, filter)
6311 ZEND_END_ARG_INFO()
6312
6313 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
6314 ZEND_ARG_INFO(0, name)
6315 ZEND_END_ARG_INFO()
6316
6317 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
6318 ZEND_ARG_INFO(0, name)
6319 ZEND_END_ARG_INFO()
6320
6321 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
6322 ZEND_ARG_INFO(0, filter)
6323 ZEND_END_ARG_INFO()
6324
6325 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
6326 ZEND_ARG_INFO(0, name)
6327 ZEND_END_ARG_INFO()
6328
6329 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
6330 ZEND_ARG_INFO(0, name)
6331 ZEND_END_ARG_INFO()
6332
6333 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
6334 ZEND_ARG_INFO(0, object)
6335 ZEND_END_ARG_INFO()
6336
6337 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
6338 ZEND_ARG_INFO(0, args)
6339 ZEND_END_ARG_INFO()
6340
6341 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6342 ZEND_END_ARG_INFO()
6343
6344 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
6345 ZEND_ARG_ARRAY_INFO(0, args, 0)
6346 ZEND_END_ARG_INFO()
6347
6348 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
6349 ZEND_ARG_INFO(0, class)
6350 ZEND_END_ARG_INFO()
6351
6352 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
6353 ZEND_ARG_INFO(0, interface)
6354 ZEND_END_ARG_INFO()
6355
6356 static const zend_function_entry reflection_class_functions[] = {
6357 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6358 ZEND_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6359 ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
6360 ZEND_ME(reflection_class, __toString, arginfo_reflection__void, 0)
6361 ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
6362 ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
6363 ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
6364 ZEND_ME(reflection_class, isAnonymous, arginfo_reflection__void, 0)
6365 ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
6366 ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
6367 ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
6368 ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
6369 ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
6370 ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0)
6371 ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0)
6372 ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
6373 ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
6374 ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
6375 ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
6376 ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
6377 ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
6378 ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
6379 ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
6380 ZEND_ME(reflection_class, getReflectionConstants, arginfo_reflection__void, 0)
6381 ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
6382 ZEND_ME(reflection_class, getReflectionConstant, arginfo_reflection_class_getConstant, 0)
6383 ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
6384 ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
6385 ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
6386 ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
6387 ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
6388 ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
6389 ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
6390 ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
6391 ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
6392 ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
6393 ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
6394 ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
6395 ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6396 ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
6397 ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
6398 ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
6399 ZEND_ME(reflection_class, getStaticProperties, arginfo_reflection__void, 0)
6400 ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
6401 ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
6402 ZEND_ME(reflection_class, getDefaultProperties, arginfo_reflection__void, 0)
6403 ZEND_ME(reflection_class, isIterable, arginfo_reflection__void, 0)
6404 ZEND_MALIAS(reflection_class, isIterateable, isIterable, arginfo_reflection__void, 0)
6405 ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
6406 ZEND_ME(reflection_class, getExtension, arginfo_reflection__void, 0)
6407 ZEND_ME(reflection_class, getExtensionName, arginfo_reflection__void, 0)
6408 ZEND_ME(reflection_class, inNamespace, arginfo_reflection__void, 0)
6409 ZEND_ME(reflection_class, getNamespaceName, arginfo_reflection__void, 0)
6410 ZEND_ME(reflection_class, getShortName, arginfo_reflection__void, 0)
6411 PHP_FE_END
6412 };
6413
6414
6415 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
6416 ZEND_ARG_INFO(0, argument)
6417 ZEND_ARG_INFO(0, return)
6418 ZEND_END_ARG_INFO()
6419
6420 ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
6421 ZEND_ARG_INFO(0, argument)
6422 ZEND_END_ARG_INFO()
6423
6424 static const zend_function_entry reflection_object_functions[] = {
6425 ZEND_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6426 ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
6427 PHP_FE_END
6428 };
6429
6430
6431 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2)
6432 ZEND_ARG_INFO(0, class)
6433 ZEND_ARG_INFO(0, name)
6434 ZEND_ARG_INFO(0, return)
6435 ZEND_END_ARG_INFO()
6436
6437 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2)
6438 ZEND_ARG_INFO(0, class)
6439 ZEND_ARG_INFO(0, name)
6440 ZEND_END_ARG_INFO()
6441
6442 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
6443 ZEND_ARG_INFO(0, object)
6444 ZEND_END_ARG_INFO()
6445
6446 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
6447 ZEND_ARG_INFO(0, object)
6448 ZEND_ARG_INFO(0, value)
6449 ZEND_END_ARG_INFO()
6450
6451 ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
6452 ZEND_ARG_INFO(0, visible)
6453 ZEND_END_ARG_INFO()
6454
6455 static const zend_function_entry reflection_property_functions[] = {
6456 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6457 ZEND_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6458 ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
6459 ZEND_ME(reflection_property, __toString, arginfo_reflection__void, 0)
6460 ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
6461 ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
6462 ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
6463 ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
6464 ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
6465 ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
6466 ZEND_ME(reflection_property, isStatic, arginfo_reflection__void, 0)
6467 ZEND_ME(reflection_property, isDefault, arginfo_reflection__void, 0)
6468 ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0)
6469 ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
6470 ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
6471 ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
6472 PHP_FE_END
6473 };
6474
6475 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant_export, 0, 0, 2)
6476 ZEND_ARG_INFO(0, class)
6477 ZEND_ARG_INFO(0, name)
6478 ZEND_ARG_INFO(0, return)
6479 ZEND_END_ARG_INFO()
6480
6481 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant___construct, 0, 0, 2)
6482 ZEND_ARG_INFO(0, class)
6483 ZEND_ARG_INFO(0, name)
6484 ZEND_END_ARG_INFO()
6485
6486 static const zend_function_entry reflection_class_constant_functions[] = {
6487 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6488 ZEND_ME(reflection_class_constant, export, arginfo_reflection_class_constant_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6489 ZEND_ME(reflection_class_constant, __construct, arginfo_reflection_class_constant___construct, 0)
6490 ZEND_ME(reflection_class_constant, __toString, arginfo_reflection__void, 0)
6491 ZEND_ME(reflection_class_constant, getName, arginfo_reflection__void, 0)
6492 ZEND_ME(reflection_class_constant, getValue, arginfo_reflection__void, 0)
6493 ZEND_ME(reflection_class_constant, isPublic, arginfo_reflection__void, 0)
6494 ZEND_ME(reflection_class_constant, isPrivate, arginfo_reflection__void, 0)
6495 ZEND_ME(reflection_class_constant, isProtected, arginfo_reflection__void, 0)
6496 ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0)
6497 ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0)
6498 ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0)
6499 PHP_FE_END
6500 };
6501
6502 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
6503 ZEND_ARG_INFO(0, function)
6504 ZEND_ARG_INFO(0, parameter)
6505 ZEND_ARG_INFO(0, return)
6506 ZEND_END_ARG_INFO()
6507
6508 ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
6509 ZEND_ARG_INFO(0, function)
6510 ZEND_ARG_INFO(0, parameter)
6511 ZEND_END_ARG_INFO()
6512
6513 static const zend_function_entry reflection_parameter_functions[] = {
6514 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6515 ZEND_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6516 ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
6517 ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
6518 ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
6519 ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
6520 ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
6521 ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
6522 ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
6523 ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
6524 ZEND_ME(reflection_parameter, hasType, arginfo_reflection__void, 0)
6525 ZEND_ME(reflection_parameter, getType, arginfo_reflection__void, 0)
6526 ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
6527 ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
6528 ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
6529 ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
6530 ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
6531 ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
6532 ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
6533 ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
6534 ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
6535 ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0)
6536 PHP_FE_END
6537 };
6538
6539 static const zend_function_entry reflection_type_functions[] = {
6540 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6541 ZEND_ME(reflection_type, allowsNull, arginfo_reflection__void, 0)
6542 ZEND_ME(reflection_type, isBuiltin, arginfo_reflection__void, 0)
6543 /* ReflectionType::__toString() is deprecated, but we currently do not mark it as such
6544 * due to bad interaction with the PHPUnit error handler and exceptions in __toString().
6545 * See PR2137. */
6546 ZEND_ME(reflection_type, __toString, arginfo_reflection__void, 0)
6547 PHP_FE_END
6548 };
6549
6550 static const zend_function_entry reflection_named_type_functions[] = {
6551 ZEND_ME(reflection_named_type, getName, arginfo_reflection__void, 0)
6552 PHP_FE_END
6553 };
6554
6555 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
6556 ZEND_ARG_INFO(0, name)
6557 ZEND_ARG_INFO(0, return)
6558 ZEND_END_ARG_INFO()
6559
6560 ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
6561 ZEND_ARG_INFO(0, name)
6562 ZEND_END_ARG_INFO()
6563
6564 static const zend_function_entry reflection_extension_functions[] = {
6565 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6566 ZEND_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6567 ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
6568 ZEND_ME(reflection_extension, __toString, arginfo_reflection__void, 0)
6569 ZEND_ME(reflection_extension, getName, arginfo_reflection__void, 0)
6570 ZEND_ME(reflection_extension, getVersion, arginfo_reflection__void, 0)
6571 ZEND_ME(reflection_extension, getFunctions, arginfo_reflection__void, 0)
6572 ZEND_ME(reflection_extension, getConstants, arginfo_reflection__void, 0)
6573 ZEND_ME(reflection_extension, getINIEntries, arginfo_reflection__void, 0)
6574 ZEND_ME(reflection_extension, getClasses, arginfo_reflection__void, 0)
6575 ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
6576 ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
6577 ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
6578 ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
6579 ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
6580 PHP_FE_END
6581 };
6582
6583 ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
6584 ZEND_ARG_INFO(0, name)
6585 ZEND_END_ARG_INFO()
6586
6587 static const zend_function_entry reflection_zend_extension_functions[] = {
6588 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6589 ZEND_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6590 ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_zend_extension___construct, 0)
6591 ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
6592 ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
6593 ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
6594 ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
6595 ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
6596 ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
6597 PHP_FE_END
6598 };
6599 /* }}} */
6600
6601 static const zend_function_entry reflection_ext_functions[] = { /* {{{ */
6602 PHP_FE_END
6603 }; /* }}} */
6604
6605 /* {{{ _reflection_write_property */
_reflection_write_property(zval * object,zval * member,zval * value,void ** cache_slot)6606 static void _reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
6607 {
6608 if ((Z_TYPE_P(member) == IS_STRING)
6609 && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STR_P(member))
6610 && ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
6611 || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
6612 {
6613 zend_throw_exception_ex(reflection_exception_ptr, 0,
6614 "Cannot set read-only property %s::$%s", ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
6615 }
6616 else
6617 {
6618 zend_std_write_property(object, member, value, cache_slot);
6619 }
6620 }
6621 /* }}} */
6622
PHP_MINIT_FUNCTION(reflection)6623 PHP_MINIT_FUNCTION(reflection) /* {{{ */
6624 {
6625 zend_class_entry _reflection_entry;
6626
6627 memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
6628 reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
6629 reflection_object_handlers.free_obj = reflection_free_objects_storage;
6630 reflection_object_handlers.clone_obj = NULL;
6631 reflection_object_handlers.write_property = _reflection_write_property;
6632 reflection_object_handlers.get_gc = reflection_get_gc;
6633
6634 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
6635 reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
6636
6637 INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
6638 reflection_ptr = zend_register_internal_class(&_reflection_entry);
6639
6640 INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
6641 reflector_ptr = zend_register_internal_interface(&_reflection_entry);
6642
6643 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
6644 _reflection_entry.create_object = reflection_objects_new;
6645 reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
6646 zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
6647 zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
6648
6649 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
6650 _reflection_entry.create_object = reflection_objects_new;
6651 reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6652 zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6653
6654 REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
6655
6656 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", reflection_generator_functions);
6657 _reflection_entry.create_object = reflection_objects_new;
6658 reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
6659
6660 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
6661 _reflection_entry.create_object = reflection_objects_new;
6662 reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
6663 zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
6664 zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6665
6666 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
6667 _reflection_entry.create_object = reflection_objects_new;
6668 reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
6669
6670 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
6671 _reflection_entry.create_object = reflection_objects_new;
6672 reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
6673
6674 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
6675 _reflection_entry.create_object = reflection_objects_new;
6676 reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6677 zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6678 zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6679
6680 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
6681 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6682 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6683 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6684 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
6685 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
6686
6687 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
6688 _reflection_entry.create_object = reflection_objects_new;
6689 reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
6690 zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
6691 zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6692
6693 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
6694 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
6695 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
6696
6697 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
6698 _reflection_entry.create_object = reflection_objects_new;
6699 reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
6700
6701 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
6702 _reflection_entry.create_object = reflection_objects_new;
6703 reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
6704 zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
6705 zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6706 zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6707
6708 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
6709 _reflection_entry.create_object = reflection_objects_new;
6710 reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
6711 zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
6712 zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6713 zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6714
6715 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
6716 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6717 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6718 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6719
6720 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
6721 _reflection_entry.create_object = reflection_objects_new;
6722 reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
6723 zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
6724 zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6725
6726 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
6727 _reflection_entry.create_object = reflection_objects_new;
6728 reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
6729 zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
6730 zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6731
6732 return SUCCESS;
6733 } /* }}} */
6734
PHP_MINFO_FUNCTION(reflection)6735 PHP_MINFO_FUNCTION(reflection) /* {{{ */
6736 {
6737 php_info_print_table_start();
6738 php_info_print_table_row(2, "Reflection", "enabled");
6739 php_info_print_table_end();
6740 } /* }}} */
6741
6742 zend_module_entry reflection_module_entry = { /* {{{ */
6743 STANDARD_MODULE_HEADER,
6744 "Reflection",
6745 reflection_ext_functions,
6746 PHP_MINIT(reflection),
6747 NULL,
6748 NULL,
6749 NULL,
6750 PHP_MINFO(reflection),
6751 PHP_REFLECTION_VERSION,
6752 STANDARD_MODULE_PROPERTIES
6753 }; /* }}} */
6754
6755 /*
6756 * Local variables:
6757 * tab-width: 4
6758 * c-basic-offset: 4
6759 * indent-tabs-mode: t
6760 * End:
6761 * vim600: noet sw=4 ts=4 fdm=marker
6762 */
6763