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