1 /*
2   +----------------------------------------------------------------------+
3   | Yet Another Framework                                                |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.php.net/license/3_01.txt                                  |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author: Xinchen Hui  <laruence@php.net>                              |
14   +----------------------------------------------------------------------+
15 */
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "php.h"
22 #include "Zend/zend_smart_str.h" /* for smart_str */
23 #include "Zend/zend_interfaces.h" /* for zend_class_serialize_deny */
24 
25 #include "php_yaf.h"
26 #include "yaf_namespace.h"
27 #include "yaf_exception.h"
28 #include "yaf_application.h" /* for yaf_application_is_module_name */
29 #include "yaf_request.h"
30 #include "yaf_router.h"
31 
32 #include "routes/yaf_route_interface.h"
33 #include "routes/yaf_route_simple.h"
34 
35 zend_class_entry *yaf_route_simple_ce;
36 static zend_object_handlers yaf_route_simple_obj_handlers;
37 
38 /** {{{ ARG_INFO
39  */
40 ZEND_BEGIN_ARG_INFO_EX(yaf_route_simple_construct_arginfo, 0, 0, 3)
41 	ZEND_ARG_INFO(0, module_name)
42     ZEND_ARG_INFO(0, controller_name)
43     ZEND_ARG_INFO(0, action_name)
ZEND_END_ARG_INFO()44 ZEND_END_ARG_INFO()
45 /* }}} */
46 
47 static HashTable *yaf_route_simple_get_properties(yaf_object *object) /* {{{ */ {
48 	zval rv;
49 	HashTable *ht;
50 	yaf_route_simple_object *simple = (yaf_route_simple_object*)(yaf_strip_obj(object));
51 
52 	if (!simple->properties) {
53 		ALLOC_HASHTABLE(simple->properties);
54 		zend_hash_init(simple->properties, 4, NULL, ZVAL_PTR_DTOR, 0);
55 
56 		ht = simple->properties;
57 		ZVAL_STR_COPY(&rv, simple->m);
58 		zend_hash_str_add(ht, "module:protected", sizeof("module:protected") - 1, &rv);
59 
60 		ZVAL_STR_COPY(&rv, simple->c);
61 		zend_hash_str_add(ht, "controller:protected", sizeof("controller:protected") - 1, &rv);
62 
63 		ZVAL_STR_COPY(&rv, simple->a);
64 		zend_hash_str_add(ht, "action:protected", sizeof("action:protected") - 1, &rv);
65 	}
66 
67 	return simple->properties;
68 }
69 /* }}} */
70 
yaf_route_simple_new(zend_class_entry * ce)71 static zend_object *yaf_route_simple_new(zend_class_entry *ce) /* {{{ */ {
72 	yaf_route_simple_object *simple = emalloc(sizeof(yaf_route_simple_object));
73 
74 	zend_object_std_init(&simple->std, ce);
75 
76 	simple->std.handlers = &yaf_route_simple_obj_handlers;
77 	simple->m = simple->c = simple->a = NULL;
78 	simple->properties = NULL;
79 
80 	return &simple->std;
81 }
82 /* }}} */
83 
yaf_route_simple_object_free(zend_object * object)84 static void yaf_route_simple_object_free(zend_object *object) /* {{{ */ {
85 	yaf_route_simple_object *simple = (yaf_route_simple_object*)object;
86 
87 	if (simple->m) {
88 		zend_string_release(simple->m);
89 	}
90 
91 	if (simple->c) {
92 		zend_string_release(simple->c);
93 	}
94 
95 	if (simple->a) {
96 		zend_string_release(simple->a);
97 	}
98 
99 	if (simple->properties) {
100 		if (GC_DELREF(simple->properties) == 0) {
101 			GC_REMOVE_FROM_BUFFER(simple->properties);
102 			zend_array_destroy(simple->properties);
103 		}
104 	}
105 
106 	zend_object_std_dtor(&simple->std);
107 }
108 /* }}} */
109 
yaf_route_simple_init(yaf_route_simple_object * simple,zend_string * m,zend_string * c,zend_string * a)110 static void yaf_route_simple_init(yaf_route_simple_object *simple, zend_string *m, zend_string *c, zend_string *a) /* {{{ */ {
111 	simple->m = zend_string_copy(m);
112 	simple->c = zend_string_copy(c);
113 	simple->a = zend_string_copy(a);
114 }
115 /* }}} */
116 
yaf_route_simple_instance(yaf_route_t * route,zend_string * m,zend_string * c,zend_string * a)117 void yaf_route_simple_instance(yaf_route_t *route, zend_string *m, zend_string *c, zend_string *a) /* {{{ */ {
118 	zend_object *simple = yaf_route_simple_new(yaf_route_simple_ce);
119 
120 	yaf_route_simple_init((yaf_route_simple_object*)simple, m, c, a);
121 
122 	ZVAL_OBJ(route, simple);
123 }
124 /* }}} */
125 
yaf_route_simple_route(yaf_route_t * route,yaf_request_t * req)126 int yaf_route_simple_route(yaf_route_t *route, yaf_request_t *req) /* {{{ */ {
127 	zval *module, *controller, *action;
128 	yaf_request_object *request = Z_YAFREQUESTOBJ_P(req);
129 	yaf_route_simple_object *simple = Z_YAFROUTESIMPLEOBJ_P(route);
130 
131 	module 	= yaf_request_query(YAF_GLOBAL_VARS_GET, simple->m);
132 	controller = yaf_request_query(YAF_GLOBAL_VARS_GET, simple->c);
133 	action = yaf_request_query(YAF_GLOBAL_VARS_GET, simple->a);
134 
135 	if (!module && !controller && !action) {
136 		return 0;
137 	}
138 
139 	if (module && Z_TYPE_P(module) == IS_STRING && yaf_application_is_module_name(Z_STR_P(module))) {
140 		yaf_request_set_module(request, Z_STR_P(module));
141 	}
142 
143 	if (controller && Z_TYPE_P(controller) == IS_STRING) {
144 		yaf_request_set_controller(request, Z_STR_P(controller));
145 	}
146 
147 	if (action && Z_TYPE_P(action) == IS_STRING) {
148 		yaf_request_set_action(request, Z_STR_P(action));
149 	}
150 
151 	return 1;
152 }
153 /* }}} */
154 
155 /** {{{ proto public Yaf_Route_Simple::route(Yaf_Request $req)
156 */
PHP_METHOD(yaf_route_simple,route)157 PHP_METHOD(yaf_route_simple, route) {
158 	yaf_request_t *request;
159 
160 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &request, yaf_request_ce) == FAILURE) {
161 		return;
162 	} else {
163 		RETURN_BOOL(yaf_route_simple_route(getThis(), request));
164 	}
165 }
166 /* }}} */
167 
yaf_route_simple_assemble(yaf_route_simple_object * simple,zval * info,zval * query)168 zend_string * yaf_route_simple_assemble(yaf_route_simple_object *simple, zval *info, zval *query) /* {{{ */ {
169 	zval *zv;
170 	smart_str uri = {0};
171 	zend_string *val;
172 
173 	smart_str_appendc(&uri, '?');
174 
175 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_MOUDLE_FORMAT))) != NULL) {
176 		val = zval_get_string(zv);
177 		smart_str_appendl(&uri, ZSTR_VAL(simple->m), ZSTR_LEN(simple->m));
178 		smart_str_appendc(&uri, '=');
179 		smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
180 		smart_str_appendc(&uri, '&');
181 		zend_string_release(val);
182 	}
183 
184 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_CONTROLLER_FORMAT))) == NULL) {
185 		yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the controller by ':c'");
186 		smart_str_free(&uri);
187 		return NULL;
188 	}
189 
190 	val = zval_get_string(zv);
191 	smart_str_appendl(&uri, ZSTR_VAL(simple->c), ZSTR_LEN(simple->c));
192 	smart_str_appendc(&uri, '=');
193 	smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
194 	smart_str_appendc(&uri, '&');
195 	zend_string_release(val);
196 
197 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_ACTION_FORMAT))) == NULL) {
198 		yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the action by ':a'");
199 		smart_str_free(&uri);
200 		return NULL;
201 	}
202 
203 	val = zval_get_string(zv);
204 	smart_str_appendl(&uri, ZSTR_VAL(simple->a), ZSTR_LEN(simple->a));
205 	smart_str_appendc(&uri, '=');
206 	smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
207 	zend_string_release(val);
208 
209 	if (query && IS_ARRAY == Z_TYPE_P(query)) {
210 		zend_string *key;
211 
212 		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(query), key, zv) {
213 			if (key) {
214 				val = zval_get_string(zv);
215 				smart_str_appendc(&uri, '&');
216 				smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key));
217 				smart_str_appendc(&uri, '=');
218 				smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
219 				zend_string_release(val);
220 			}
221 		} ZEND_HASH_FOREACH_END();
222 	}
223 
224 	smart_str_0(&uri);
225 	return uri.s;
226 }
227 /* }}} */
228 
229 /** {{{ proto public Yaf_Route_Simple::__construct(string $module, string $controller, string $action)
230  */
PHP_METHOD(yaf_route_simple,__construct)231 PHP_METHOD(yaf_route_simple, __construct) {
232 	zend_string *m, *c, *a;
233 
234 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "SSS", &m, &c, &a) == FAILURE) {
235 		return;
236 	}
237 
238 	yaf_route_simple_init(Z_YAFROUTESIMPLEOBJ_P(getThis()), m, c, a);
239 }
240 /* }}} */
241 
242 /** {{{ proto public Yaf_Route_Simple::assemble(array $info[, array $query = NULL])
243  */
PHP_METHOD(yaf_route_simple,assemble)244 PHP_METHOD(yaf_route_simple, assemble) {
245 	zend_string *str;
246     zval *info, *query = NULL;
247 
248     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|a", &info, &query) == FAILURE) {
249         return;
250     }
251 
252 	if ((str = yaf_route_simple_assemble(Z_YAFROUTESIMPLEOBJ_P(getThis()), info, query))) {
253 		RETURN_STR(str);
254 	}
255 
256 	RETURN_NULL();
257 }
258 /* }}} */
259 
260 /** {{{ yaf_route_simple_methods
261  */
262 zend_function_entry yaf_route_simple_methods[] = {
263 	PHP_ME(yaf_route_simple, __construct, yaf_route_simple_construct_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
264 	PHP_ME(yaf_route_simple, route, yaf_route_route_arginfo, ZEND_ACC_PUBLIC)
265 	PHP_ME(yaf_route_simple, assemble, yaf_route_assemble_arginfo, ZEND_ACC_PUBLIC)
266 	{NULL, NULL, NULL}
267 };
268 /* }}} */
269 
270 /** {{{ YAF_STARTUP_FUNCTION
271  */
YAF_STARTUP_FUNCTION(route_simple)272 YAF_STARTUP_FUNCTION(route_simple) {
273 	zend_class_entry ce;
274 
275 	YAF_INIT_CLASS_ENTRY(ce, "Yaf_Route_Simple", "Yaf\\Route\\Simple", yaf_route_simple_methods);
276 	yaf_route_simple_ce = zend_register_internal_class(&ce);
277 	yaf_route_simple_ce->create_object = yaf_route_simple_new;
278 	yaf_route_simple_ce->ce_flags |= ZEND_ACC_FINAL;
279 	yaf_route_simple_ce->serialize = zend_class_serialize_deny;
280 	yaf_route_simple_ce->unserialize = zend_class_unserialize_deny;
281 
282 	zend_class_implements(yaf_route_simple_ce, 1, yaf_route_ce);
283 
284 	memcpy(&yaf_route_simple_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
285 	yaf_route_simple_obj_handlers.free_obj = yaf_route_simple_object_free;
286 	yaf_route_simple_obj_handlers.clone_obj = NULL;
287 	yaf_route_simple_obj_handlers.get_gc = yaf_fake_get_gc;
288 	yaf_route_simple_obj_handlers.get_properties = yaf_route_simple_get_properties;
289 
290 	return SUCCESS;
291 }
292 /* }}} */
293 
294 /*
295  * Local variables:
296  * tab-width: 4
297  * c-basic-offset: 4
298  * End:
299  * vim600: noet sw=4 ts=4 fdm=marker
300  * vim<600: noet sw=4 ts=4
301  */
302