00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "onphp.h"
00013 #include "onphp_core.h"
00014
00015 #include "zend_globals.h"
00016 #include "zend_exceptions.h"
00017
00018 #include "core/Base/Singleton.h"
00019 #include "core/Exceptions.h"
00020
00021
00022 static zval *instances = NULL;
00023
00024 ONPHP_METHOD(Singleton, __construct) {}
00025 ONPHP_METHOD(Singleton, __clone) {}
00026 ONPHP_METHOD(Singleton, __sleep) {}
00027
00028 ONPHP_METHOD(Singleton, getInstance)
00029 {
00030 char *name;
00031 int length, argc = ZEND_NUM_ARGS();
00032 zend_class_entry **cep;
00033 zval *object, *args;
00034 zval **stored;
00035 zval ***params = NULL;
00036
00037 if (argc < 1) {
00038 WRONG_PARAM_COUNT;
00039 }
00040
00041 params = safe_emalloc(sizeof(zval **), argc, 0);
00042
00043 if (zend_get_parameters_array_ex(argc, params) == FAILURE) {
00044 zend_throw_exception_ex(
00045 onphp_ce_BaseException,
00046 0 TSRMLS_CC,
00047 "Failed to get calling arguments for object creation"
00048 );
00049 efree(params);
00050 RETURN_NULL();
00051 }
00052
00053
00054 if (argc > 2) {
00055 int i;
00056 ALLOC_INIT_ZVAL(args);
00057 array_init(args);
00058
00059 for (i = 1; i < argc; i++) {
00060 add_next_index_zval(args, *params[i]);
00061 }
00062
00063 params[1] = &args;
00064 argc = 2;
00065 }
00066
00067 name = estrdup(Z_STRVAL_PP(params[0]));
00068
00069 length = strlen(name);
00070
00071 if (
00072 zend_hash_find(
00073 Z_ARRVAL_P(instances),
00074 name,
00075 length + 1,
00076 (void **) &stored
00077 )
00078 == SUCCESS
00079 ) {
00080 efree(params);
00081 efree(name);
00082
00083 object = *stored;
00084
00085 zval_copy_ctor(object);
00086 } else {
00087
00088 if (zend_lookup_class(name, length, &cep TSRMLS_CC) == SUCCESS) {
00089 zval *retval_ptr;
00090 zend_fcall_info fci;
00091 zend_fcall_info_cache fcc;
00092 zend_class_entry *ce = *cep;
00093
00094
00095 efree(name);
00096
00097 if (!instanceof_function(ce, onphp_ce_Singleton TSRMLS_CC)) {
00098 zend_throw_exception_ex(
00099 onphp_ce_WrongArgumentException,
00100 0 TSRMLS_CC,
00101 "Class '%s' is something not a Singleton's child",
00102 ce->name
00103 );
00104 efree(params);
00105 return;
00106 }
00107
00108
00109
00110 if (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE) {
00111 zend_throw_exception_ex(
00112 onphp_ce_BaseException,
00113 0 TSRMLS_CC,
00114 "Can not call private constructor for '%s' creation",
00115 ce->name
00116 );
00117 efree(params);
00118 return;
00119 } else if (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC) {
00120 zend_throw_exception_ex(
00121 onphp_ce_BaseException,
00122 0 TSRMLS_CC,
00123 "Don't want to deal with '%s' class "
00124 "due to public constructor there",
00125 ce->name
00126 );
00127 efree(params);
00128 return;
00129 }
00130
00131 MAKE_STD_ZVAL(object);
00132 object_init_ex(object, ce);
00133
00134 fci.size = sizeof(fci);
00135 fci.function_table = EG(function_table);
00136 fci.function_name = NULL;
00137 fci.symbol_table = NULL;
00138 fci.object_pp = &object;
00139 fci.retval_ptr_ptr = &retval_ptr;
00140 fci.param_count = argc - 1;
00141 fci.params = params + 1;
00142
00143 fcc.initialized = 1;
00144 fcc.function_handler = ce->constructor;
00145 fcc.calling_scope = EG(scope);
00146 fcc.object_pp = &object;
00147
00148 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
00149 zend_throw_exception_ex(
00150 onphp_ce_BaseException,
00151 0 TSRMLS_CC,
00152 "Failed to call '%s' constructor",
00153 ce->name
00154 );
00155 }
00156
00157 efree(params);
00158
00159 if (retval_ptr) {
00160 zval_ptr_dtor(&retval_ptr);
00161 }
00162
00163 if (EG(exception)) {
00164 return;
00165 }
00166
00167 add_assoc_zval_ex(instances, ce->name, length + 1, object);
00168 }
00169 }
00170
00171 RETURN_ZVAL(object, 1, 0);
00172 }
00173
00174 ONPHP_METHOD(Singleton, getAllInstances)
00175 {
00176 RETURN_ZVAL(instances, 1, 0);
00177 }
00178
00179 PHP_RINIT_FUNCTION(Singleton)
00180 {
00181 ALLOC_INIT_ZVAL(instances);
00182 array_init(instances);
00183
00184 return SUCCESS;
00185 }
00186
00187 PHP_RSHUTDOWN_FUNCTION(Singleton)
00188 {
00189 zval_ptr_dtor(&instances);
00190
00191 return SUCCESS;
00192 }
00193
00194 static ONPHP_ARGINFO_ONE;
00195
00196 zend_function_entry onphp_funcs_Singleton[] = {
00197 ONPHP_ME(Singleton, __construct, NULL, ZEND_ACC_PROTECTED | ZEND_ACC_CTOR)
00198 ONPHP_ME(Singleton, getInstance, arginfo_one, ZEND_ACC_FINAL | ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
00199 ONPHP_ME(Singleton, getAllInstances, NULL, ZEND_ACC_FINAL | ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
00200 ONPHP_ME(Singleton, __clone, NULL, ZEND_ACC_FINAL | ZEND_ACC_PRIVATE)
00201 ONPHP_ME(Singleton, __sleep, NULL, ZEND_ACC_FINAL | ZEND_ACC_PRIVATE)
00202 {NULL, NULL, NULL}
00203 };