PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/routes/yaf_route_map.c

https://gitlab.com/oytunistrator/yaf
C | 323 lines | 225 code | 49 blank | 49 comment | 67 complexity | 0202b4d93b309db3df4dc83dee974691 MD5 | raw file
  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. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "ext/standard/php_smart_str.h" /* for smart_str */
  21. #include "php_yaf.h"
  22. #include "yaf_namespace.h"
  23. #include "yaf_exception.h"
  24. #include "yaf_request.h"
  25. #include "yaf_router.h"
  26. #include "routes/yaf_route_interface.h"
  27. #include "routes/yaf_route_map.h"
  28. zend_class_entry *yaf_route_map_ce;
  29. /** {{{ ARG_INFO
  30. */
  31. ZEND_BEGIN_ARG_INFO_EX(yaf_route_map_construct_arginfo, 0, 0, 0)
  32. ZEND_ARG_INFO(0, controller_prefer)
  33. ZEND_ARG_INFO(0, delimiter)
  34. ZEND_END_ARG_INFO()
  35. /* }}} */
  36. /* {{{ yaf_route_t * yaf_route_map_instance(yaf_route_t *this_ptr, zend_bool controller_prefer, char *delim, uint len TSRMLS_DC)
  37. */
  38. yaf_route_t * yaf_route_map_instance(yaf_route_t *this_ptr, zend_bool controller_prefer, char *delim, uint len TSRMLS_DC) {
  39. yaf_route_t *instance;
  40. if (this_ptr) {
  41. instance = this_ptr;
  42. } else {
  43. MAKE_STD_ZVAL(instance);
  44. object_init_ex(instance, yaf_route_map_ce);
  45. }
  46. if (controller_prefer) {
  47. zend_update_property_bool(yaf_route_map_ce, instance,
  48. ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1 TSRMLS_CC);
  49. }
  50. if (delim && len) {
  51. zend_update_property_stringl(yaf_route_map_ce, instance,
  52. ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), delim, len TSRMLS_CC);
  53. }
  54. return instance;
  55. }
  56. /* }}} */
  57. /** {{{ int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request TSRMLS_DC)
  58. */
  59. int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request TSRMLS_DC) {
  60. zval *ctl_prefer, *delimer, *zuri, *base_uri, *params;
  61. char *req_uri, *tmp, *rest, *ptrptr, *seg;
  62. char *query_str = NULL;
  63. uint seg_len = 0;
  64. smart_str route_result = {0};
  65. zuri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_URI), 1 TSRMLS_CC);
  66. base_uri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_BASE), 1 TSRMLS_CC);
  67. ctl_prefer = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1 TSRMLS_CC);
  68. delimer = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), 1 TSRMLS_CC);
  69. if (base_uri && IS_STRING == Z_TYPE_P(base_uri)
  70. && !strncasecmp(Z_STRVAL_P(zuri), Z_STRVAL_P(base_uri), Z_STRLEN_P(base_uri))) {
  71. req_uri = estrdup(Z_STRVAL_P(zuri) + Z_STRLEN_P(base_uri));
  72. } else {
  73. req_uri = estrdup(Z_STRVAL_P(zuri));
  74. }
  75. if (Z_TYPE_P(delimer) == IS_STRING
  76. && Z_STRLEN_P(delimer)) {
  77. if ((query_str = strstr(req_uri, Z_STRVAL_P(delimer))) != NULL
  78. && *(query_str - 1) == '/') {
  79. tmp = req_uri;
  80. rest = query_str + Z_STRLEN_P(delimer);
  81. if (*rest == '\0') {
  82. req_uri = estrndup(req_uri, query_str - req_uri);
  83. query_str = NULL;
  84. efree(tmp);
  85. } else if (*rest == '/') {
  86. req_uri = estrndup(req_uri, query_str - req_uri);
  87. query_str = estrdup(rest);
  88. efree(tmp);
  89. } else {
  90. query_str = NULL;
  91. }
  92. } else {
  93. query_str = NULL;
  94. }
  95. }
  96. seg = php_strtok_r(req_uri, YAF_ROUTER_URL_DELIMIETER, &ptrptr);
  97. while (seg) {
  98. seg_len = strlen(seg);
  99. if (seg_len) {
  100. smart_str_appendl(&route_result, seg, seg_len);
  101. }
  102. smart_str_appendc(&route_result, '_');
  103. seg = php_strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &ptrptr);
  104. }
  105. if (route_result.len) {
  106. if (Z_BVAL_P(ctl_prefer)) {
  107. zend_update_property_stringl(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_CONTROLLER), route_result.c, route_result.len - 1 TSRMLS_CC);
  108. } else {
  109. zend_update_property_stringl(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_ACTION), route_result.c, route_result.len - 1 TSRMLS_CC);
  110. }
  111. efree(route_result.c);
  112. }
  113. if (query_str) {
  114. params = yaf_router_parse_parameters(query_str TSRMLS_CC);
  115. (void)yaf_request_set_params_multi(request, params TSRMLS_CC);
  116. zval_ptr_dtor(&params);
  117. efree(query_str);
  118. }
  119. efree(req_uri);
  120. return 1;
  121. }
  122. /* }}} */
  123. /** {{{ proto public Yaf_Route_Simple::route(Yaf_Request $req)
  124. */
  125. PHP_METHOD(yaf_route_map, route) {
  126. yaf_request_t *request;
  127. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, yaf_request_ce) == FAILURE) {
  128. return;
  129. } else {
  130. RETURN_BOOL(yaf_route_map_route(getThis(), request TSRMLS_CC));
  131. }
  132. }
  133. /* }}} */
  134. /** {{{ zval * yaf_route_map_assemble(zval *info, zval *query TSRMLS_DC)
  135. */
  136. zval * yaf_route_map_assemble(yaf_route_t *this_ptr, zval *info, zval *query TSRMLS_DC) {
  137. char *tmp, *ptrptr, *pname;
  138. smart_str tvalue = {0};
  139. uint tmp_len, has_delim = 0;
  140. zval *uri, *delim, *ctl_prefer, **tmp_data;
  141. MAKE_STD_ZVAL(uri);
  142. ctl_prefer = zend_read_property(yaf_route_map_ce, this_ptr, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1 TSRMLS_CC);
  143. delim = zend_read_property(yaf_route_map_ce, this_ptr, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), 1 TSRMLS_CC);
  144. if (IS_STRING == Z_TYPE_P(delim) && Z_STRLEN_P(delim)) {
  145. has_delim = 1;
  146. }
  147. do {
  148. if (Z_BVAL_P(ctl_prefer)) {
  149. if (zend_hash_find(Z_ARRVAL_P(info), ZEND_STRS(YAF_ROUTE_ASSEMBLE_ACTION_FORMAT), (void **)&tmp_data) == SUCCESS) {
  150. pname = estrndup(Z_STRVAL_PP(tmp_data), Z_STRLEN_PP(tmp_data));
  151. } else {
  152. yaf_trigger_error(YAF_ERR_TYPE_ERROR TSRMLS_CC, "%s", "Undefined the 'action' parameter for the 1st parameter");
  153. break;
  154. }
  155. } else {
  156. if (zend_hash_find(Z_ARRVAL_P(info), ZEND_STRS(YAF_ROUTE_ASSEMBLE_CONTROLLER_FORMAT), (void **)&tmp_data) == SUCCESS) {
  157. pname = estrndup(Z_STRVAL_PP(tmp_data), Z_STRLEN_PP(tmp_data));
  158. } else {
  159. yaf_trigger_error(YAF_ERR_TYPE_ERROR TSRMLS_CC, "%s", "Undefined the 'controller' parameter for the 1st parameter");
  160. break;
  161. }
  162. }
  163. tmp = php_strtok_r(pname, "_", &ptrptr);
  164. while(tmp) {
  165. tmp_len = strlen(tmp);
  166. if (tmp_len) {
  167. smart_str_appendc(&tvalue, '/');
  168. smart_str_appendl(&tvalue, tmp, tmp_len);
  169. }
  170. tmp = php_strtok_r(NULL, "_", &ptrptr);
  171. }
  172. efree(pname);
  173. if (query && IS_ARRAY == Z_TYPE_P(query)) {
  174. uint key_len, i = 0;
  175. char *key;
  176. ulong key_idx;
  177. zval **tmp_data;
  178. if (has_delim) {
  179. smart_str_appendc(&tvalue, '/');
  180. smart_str_appendl(&tvalue, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
  181. }
  182. for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(query));
  183. zend_hash_get_current_data(Z_ARRVAL_P(query), (void **)&tmp_data) == SUCCESS;
  184. zend_hash_move_forward(Z_ARRVAL_P(query))) {
  185. if (IS_STRING == Z_TYPE_PP(tmp_data)
  186. && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(query), &key, &key_len, &key_idx, 0, NULL)) {
  187. if (has_delim) {
  188. smart_str_appendc(&tvalue, '/');
  189. smart_str_appendl(&tvalue, key, key_len - 1);
  190. smart_str_appendc(&tvalue, '/');
  191. smart_str_appendl(&tvalue, Z_STRVAL_PP(tmp_data), Z_STRLEN_PP(tmp_data));
  192. } else {
  193. if (i == 0) {
  194. smart_str_appendc(&tvalue, '?');
  195. smart_str_appendl(&tvalue, key, key_len - 1);
  196. smart_str_appendc(&tvalue, '=');
  197. smart_str_appendl(&tvalue, Z_STRVAL_PP(tmp_data), Z_STRLEN_PP(tmp_data));
  198. } else {
  199. smart_str_appendc(&tvalue, '&');
  200. smart_str_appendl(&tvalue, key, key_len - 1);
  201. smart_str_appendc(&tvalue, '=');
  202. smart_str_appendl(&tvalue, Z_STRVAL_PP(tmp_data), Z_STRLEN_PP(tmp_data));
  203. }
  204. }
  205. }
  206. i += 1;
  207. }
  208. }
  209. smart_str_0(&tvalue);
  210. ZVAL_STRING(uri, tvalue.c, 1);
  211. smart_str_free(&tvalue);
  212. return uri;
  213. } while (0);
  214. ZVAL_NULL(uri);
  215. return uri;
  216. }
  217. /** {{{ proto public Yaf_Route_Simple::__construct(bool $controller_prefer=FALSE, string $delimer = '#!')
  218. */
  219. PHP_METHOD(yaf_route_map, __construct) {
  220. char *delim = NULL;
  221. uint delim_len = 0;
  222. zend_bool controller_prefer = 0;
  223. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs",
  224. &controller_prefer, &delim, &delim_len) == FAILURE) {
  225. YAF_UNINITIALIZED_OBJECT(getThis());
  226. return;
  227. }
  228. (void)yaf_route_map_instance(getThis(), controller_prefer, delim, delim_len TSRMLS_CC);
  229. }
  230. /* }}} */
  231. /** {{{ proto public Yaf_Route_Map::assemble(array $info[, array $query = NULL])
  232. */
  233. PHP_METHOD(yaf_route_map, assemble) {
  234. zval *info, *query = NULL;
  235. zval *return_uri;
  236. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|a", &info, &query) == FAILURE) {
  237. return;
  238. } else {
  239. if ((return_uri = yaf_route_map_assemble(getThis(), info, query TSRMLS_CC))) {
  240. RETURN_ZVAL(return_uri, 0, 1);
  241. }
  242. }
  243. }
  244. /* }}} */
  245. /** {{{ yaf_route_map_methods
  246. */
  247. zend_function_entry yaf_route_map_methods[] = {
  248. PHP_ME(yaf_route_map, __construct, yaf_route_map_construct_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
  249. PHP_ME(yaf_route_map, route, yaf_route_route_arginfo, ZEND_ACC_PUBLIC)
  250. PHP_ME(yaf_route_map, assemble, yaf_route_assemble_arginfo, ZEND_ACC_PUBLIC)
  251. {NULL, NULL, NULL}
  252. };
  253. /* }}} */
  254. /** {{{ YAF_STARTUP_FUNCTION
  255. */
  256. YAF_STARTUP_FUNCTION(route_map) {
  257. zend_class_entry ce;
  258. YAF_INIT_CLASS_ENTRY(ce, "Yaf_Route_Map", "Yaf\\Route\\Map", yaf_route_map_methods);
  259. yaf_route_map_ce = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
  260. zend_class_implements(yaf_route_map_ce TSRMLS_CC, 1, yaf_route_ce);
  261. yaf_route_map_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
  262. zend_declare_property_bool(yaf_route_map_ce, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 0, ZEND_ACC_PROTECTED TSRMLS_CC);
  263. zend_declare_property_null(yaf_route_map_ce, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), ZEND_ACC_PROTECTED TSRMLS_CC);
  264. return SUCCESS;
  265. }
  266. /* }}} */
  267. /*
  268. * Local variables:
  269. * tab-width: 4
  270. * c-basic-offset: 4
  271. * End:
  272. * vim600: noet sw=4 ts=4 fdm=marker
  273. * vim<600: noet sw=4 ts=4
  274. */