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