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