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