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_request.h"
29 
30 #include "yaf_router.h"
31 #include "routes/yaf_route_interface.h"
32 #include "routes/yaf_route_static.h" /* for yaf_route_pathinfo_route */
33 #include "routes/yaf_route_supervar.h"
34 
35 zend_class_entry *yaf_route_supervar_ce;
36 static zend_object_handlers yaf_route_supervar_obj_handlers;
37 
38 /** {{{ ARG_INFO
39  */
40 ZEND_BEGIN_ARG_INFO_EX(yaf_route_supervar_construct_arginfo, 0, 0, 1)
41     ZEND_ARG_INFO(0, supervar_name)
ZEND_END_ARG_INFO()42 ZEND_END_ARG_INFO()
43 /* }}} */
44 
45 static HashTable *yaf_route_supervar_get_properties(yaf_object *object) /* {{{ */ {
46 	zval rv;
47 	yaf_route_supervar_object *super = (yaf_route_supervar_object*)(yaf_strip_obj(object));
48 
49 	if (!super->properties) {
50 		ALLOC_HASHTABLE(super->properties);
51 		zend_hash_init(super->properties, 2, NULL, ZVAL_PTR_DTOR, 0);
52 
53 		ZVAL_STR_COPY(&rv, super->varname);
54 		zend_hash_str_add(super->properties, "varname:protected", sizeof("varname:protected") - 1, &rv);
55 	}
56 
57 	return super->properties;
58 }
59 /* }}} */
60 
yaf_route_supervar_new(zend_class_entry * ce)61 static zend_object *yaf_route_supervar_new(zend_class_entry *ce) /* {{{ */ {
62 	yaf_route_supervar_object *supervar = emalloc(sizeof(yaf_route_supervar_object));
63 
64 	zend_object_std_init(&supervar->std, ce);
65 
66 	supervar->std.handlers = &yaf_route_supervar_obj_handlers;
67 
68 	supervar->varname = NULL;
69 	supervar->properties = NULL;
70 
71 	return &supervar->std;
72 }
73 /* }}} */
74 
yaf_route_supervar_object_free(zend_object * object)75 static void yaf_route_supervar_object_free(zend_object *object) /* {{{ */ {
76 	yaf_route_supervar_object *supervar = (yaf_route_supervar_object*)object;
77 
78 	zend_string_release(supervar->varname);
79 
80 	if (supervar->properties) {
81 		if (GC_DELREF(supervar->properties) == 0) {
82 			GC_REMOVE_FROM_BUFFER(supervar->properties);
83 			zend_array_destroy(supervar->properties);
84 		}
85 	}
86 
87 	zend_object_std_dtor(&supervar->std);
88 }
89 /* }}} */
90 
yaf_route_supervar_route(yaf_route_t * route,yaf_request_t * req)91 int yaf_route_supervar_route(yaf_route_t *route, yaf_request_t *req) /* {{{ */ {
92 	zval *uri;
93 	yaf_route_supervar_object *super = Z_YAFROUTESUPEROBJ_P(route);
94 
95 	uri = yaf_request_query(YAF_GLOBAL_VARS_GET, super->varname);
96 
97 	if (UNEXPECTED(uri == NULL)) {
98 		return 0;
99 	}
100 
101 	yaf_route_pathinfo_route(Z_YAFREQUESTOBJ_P(req), Z_STRVAL_P(uri), Z_STRLEN_P(uri));
102 
103 	return 1;
104 }
105 /* }}} */
106 
yaf_route_supervar_init(yaf_route_supervar_object * super,zend_string * varname)107 static void yaf_route_supervar_init(yaf_route_supervar_object *super, zend_string *varname) /* {{{ */ {
108 	super->varname = zend_string_copy(varname);
109 }
110 /* }}} */
111 
yaf_route_supervar_instance(yaf_route_t * route,zend_string * varname)112 void yaf_route_supervar_instance(yaf_route_t *route, zend_string *varname) /* {{{ */ {
113 	zend_object *router = yaf_route_supervar_new(yaf_route_supervar_ce);
114 
115 	yaf_route_supervar_init((yaf_route_supervar_object*)router, varname);
116 
117 	ZVAL_OBJ(route, router);
118 }
119 /* }}} */
120 
yaf_route_supervar_assemble(yaf_route_supervar_object * super,zval * info,zval * query)121 zend_string * yaf_route_supervar_assemble(yaf_route_supervar_object *super, zval *info, zval *query) /* {{{ */ {
122 	zval *zv;
123 	smart_str uri = {0};
124 	zend_string *val;
125 
126 
127 	smart_str_appendc(&uri, '?');
128 	smart_str_appendl(&uri, ZSTR_VAL(super->varname), ZSTR_LEN(super->varname));
129 	smart_str_appendc(&uri, '=');
130 
131 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_MOUDLE_FORMAT))) != NULL) {
132 		val = zval_get_string(zv);
133 		smart_str_appendc(&uri, '/');
134 		smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
135 		zend_string_release(val);
136 	}
137 
138 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_CONTROLLER_FORMAT))) == NULL) {
139 		yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the controller by ':c'");
140 		smart_str_free(&uri);
141 		return NULL;
142 	}
143 
144 	val = zval_get_string(zv);
145 	smart_str_appendc(&uri, '/');
146 	smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
147 	zend_string_release(val);
148 
149 	if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_ACTION_FORMAT))) == NULL) {
150 		yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the action by ':a'");
151 		smart_str_free(&uri);
152 		return NULL;
153 	}
154 
155 	val = zval_get_string(zv);
156 	smart_str_appendc(&uri, '/');
157 	smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
158 	zend_string_release(val);
159 
160 	if (query && IS_ARRAY == Z_TYPE_P(query)) {
161 		zend_string *key;
162 
163 		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(query), key, zv) {
164 			if (key) {
165 				val = zval_get_string(zv);
166 				smart_str_appendc(&uri, '&');
167 				smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key));
168 				smart_str_appendc(&uri, '=');
169 				smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
170 				zend_string_release(val);
171 			}
172 		} ZEND_HASH_FOREACH_END();
173 	}
174 
175 	smart_str_0(&uri);
176 	return uri.s;
177 }
178 /* }}} */
179 
180 /** {{{ proto public Yaf_Route_Supervar::route(Yaf_Request_Abstarct $request)
181  */
PHP_METHOD(yaf_route_supervar,route)182 PHP_METHOD(yaf_route_supervar, route) {
183 	yaf_request_t *request;
184 
185 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &request, yaf_request_ce) == FAILURE) {
186 		return;
187 	}
188 	RETURN_BOOL(yaf_route_supervar_route(getThis(), request));
189 }
190 /** }}} */
191 
192 /** {{{ proto public Yaf_Route_Supervar::__construct(string $varname)
193 */
PHP_METHOD(yaf_route_supervar,__construct)194 PHP_METHOD(yaf_route_supervar, __construct) {
195 	zend_string *varname;
196 
197     if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "S", &varname) == FAILURE) {
198         return;
199     }
200 
201 	yaf_route_supervar_init(Z_YAFROUTESUPEROBJ_P(getThis()), varname);
202 }
203 /** }}} */
204 
205 /** {{{ proto public Yaf_Route_Supervar::assemble(array $info[, array $query = NULL])
206 */
PHP_METHOD(yaf_route_supervar,assemble)207 PHP_METHOD(yaf_route_supervar, assemble) {
208 	zend_string *str;
209     zval *info, *query = NULL;
210 
211     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|a", &info, &query) == FAILURE) {
212         return;
213     }
214 	if ((str = yaf_route_supervar_assemble(Z_YAFROUTESUPEROBJ_P(getThis()), info, query))) {
215 		RETURN_STR(str);
216 	}
217 	RETURN_NULL();
218 }
219 /* }}} */
220 
221 /** {{{ yaf_route_supervar_methods
222 */
223 zend_function_entry yaf_route_supervar_methods[] = {
224 	PHP_ME(yaf_route_supervar, __construct, yaf_route_supervar_construct_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
225 	PHP_ME(yaf_route_supervar, route, yaf_route_route_arginfo, ZEND_ACC_PUBLIC)
226 	PHP_ME(yaf_route_supervar, assemble, yaf_route_assemble_arginfo, ZEND_ACC_PUBLIC)
227 	{NULL, NULL, NULL}
228 };
229 /* }}} */
230 
231 /** {{{ YAF_STARTUP_FUNCTION
232  */
YAF_STARTUP_FUNCTION(route_supervar)233 YAF_STARTUP_FUNCTION(route_supervar) {
234 	zend_class_entry ce;
235 	YAF_INIT_CLASS_ENTRY(ce, "Yaf_Route_Supervar", "Yaf\\Route\\Supervar", yaf_route_supervar_methods);
236 	yaf_route_supervar_ce = zend_register_internal_class(&ce);
237 	yaf_route_supervar_ce->ce_flags |= ZEND_ACC_FINAL;
238 
239 	yaf_route_supervar_ce->create_object = yaf_route_supervar_new;
240 	yaf_route_supervar_ce->serialize = zend_class_serialize_deny;
241 	yaf_route_supervar_ce->unserialize = zend_class_unserialize_deny;
242 
243 	zend_class_implements(yaf_route_supervar_ce, 1, yaf_route_ce);
244 
245 	memcpy(&yaf_route_supervar_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
246 	yaf_route_supervar_obj_handlers.free_obj = yaf_route_supervar_object_free;
247 	yaf_route_supervar_obj_handlers.clone_obj = NULL;
248 	yaf_route_supervar_obj_handlers.get_gc = yaf_fake_get_gc;
249 	yaf_route_supervar_obj_handlers.get_properties = yaf_route_supervar_get_properties;
250 
251 
252 	return SUCCESS;
253 }
254 /* }}} */
255 
256 /*
257  * Local variables:
258  * tab-width: 4
259  * c-basic-offset: 4
260  * End:
261  * vim600: noet sw=4 ts=4 fdm=marker
262  * vim<600: noet sw=4 ts=4
263  */
264 
265