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