/** * Produce the routing parameters from the rewrite information * * @param string $uri */ PHP_METHOD(Phalcon_Mvc_Router_Annotations, handle){ zval *uri = NULL, *real_uri = NULL, *processed, *annotations_service = NULL; zval *handlers, *controller_suffix, *scope = NULL, *prefix = NULL; zval *dependency_injector = NULL, *service = NULL, *handler = NULL; zval *controller_name = NULL; zval *namespace_name = NULL, *module_name = NULL, *suffixed = NULL; zval *handler_annotations = NULL, *class_annotations = NULL; zval *annotations = NULL, *annotation = NULL, *method_annotations = NULL; zval *collection = NULL, *method = NULL; HashTable *ah0, *ah1, *ah2, *ah3; HashPosition hp0, hp1, hp2, hp3; zval **hd; PHALCON_MM_GROW(); phalcon_fetch_params(1, 0, 1, &uri); if (!uri) { uri = PHALCON_GLOBAL(z_null); } if (!zend_is_true(uri)) { /** * If 'uri' isn't passed as parameter it reads $_GET['_url'] */ PHALCON_CALL_METHOD(&real_uri, this_ptr, "getrewriteuri"); } else { PHALCON_CPY_WRT(real_uri, uri); } PHALCON_OBS_VAR(processed); phalcon_read_property_this(&processed, this_ptr, SL("_processed"), PH_NOISY TSRMLS_CC); if (!zend_is_true(processed)) { PHALCON_INIT_VAR(annotations_service); PHALCON_OBS_VAR(handlers); phalcon_read_property_this(&handlers, this_ptr, SL("_handlers"), PH_NOISY TSRMLS_CC); if (Z_TYPE_P(handlers) == IS_ARRAY) { PHALCON_OBS_VAR(controller_suffix); phalcon_read_property_this(&controller_suffix, this_ptr, SL("_controllerSuffix"), PH_NOISY TSRMLS_CC); phalcon_is_iterable(handlers, &ah0, &hp0, 0, 0); while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) { PHALCON_GET_HVALUE(scope); if (Z_TYPE_P(scope) == IS_ARRAY) { /** * A prefix (if any) must be in position 0 */ PHALCON_OBS_NVAR(prefix); phalcon_array_fetch_long(&prefix, scope, 0, PH_NOISY); if (Z_TYPE_P(prefix) == IS_STRING) { if (!phalcon_start_with(real_uri, prefix, NULL)) { zend_hash_move_forward_ex(ah0, &hp0); continue; } } if (Z_TYPE_P(annotations_service) != IS_OBJECT) { PHALCON_OBS_NVAR(dependency_injector); phalcon_read_property_this(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY TSRMLS_CC); if (Z_TYPE_P(dependency_injector) != IS_OBJECT) { PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_router_exception_ce, "A dependency injection container is required to access the 'annotations' service"); return; } PHALCON_INIT_NVAR(service); ZVAL_STRING(service, "annotations", 1); PHALCON_CALL_METHOD(&annotations_service, dependency_injector, "getshared", service); PHALCON_VERIFY_INTERFACE(annotations_service, phalcon_annotations_adapterinterface_ce); } /** * The controller must be in position 1 */ PHALCON_OBS_NVAR(handler); phalcon_array_fetch_long(&handler, scope, 1, PH_NOISY); if (phalcon_memnstr_str(handler, SL("\\"))) { /** * Extract the real class name from the namespaced class */ PHALCON_INIT_NVAR(controller_name); phalcon_get_class_ns(controller_name, handler, 0 TSRMLS_CC); /** * Extract the namespace from the namespaced class */ PHALCON_INIT_NVAR(namespace_name); phalcon_get_ns_class(namespace_name, handler, 0 TSRMLS_CC); } else { PHALCON_CPY_WRT(controller_name, handler); PHALCON_INIT_NVAR(namespace_name); } phalcon_update_property_null(this_ptr, SL("_routePrefix") TSRMLS_CC); /** * Check if the scope has a module associated */ if (phalcon_array_isset_long(scope, 2)) { PHALCON_OBS_NVAR(module_name); phalcon_array_fetch_long(&module_name, scope, 2, PH_NOISY); } else { PHALCON_INIT_NVAR(module_name); } PHALCON_INIT_NVAR(suffixed); PHALCON_CONCAT_VV(suffixed, handler, controller_suffix); /** * Get the annotations from the class */ PHALCON_CALL_METHOD(&handler_annotations, annotations_service, "get", suffixed); /** * Process class annotations */ PHALCON_CALL_METHOD(&class_annotations, handler_annotations, "getclassannotations"); if (Z_TYPE_P(class_annotations) == IS_OBJECT) { /** * Process class annotations */ PHALCON_CALL_METHOD(&annotations, class_annotations, "getannotations"); if (Z_TYPE_P(annotations) == IS_ARRAY) { phalcon_is_iterable(annotations, &ah1, &hp1, 0, 0); while (zend_hash_get_current_data_ex(ah1, (void**) &hd, &hp1) == SUCCESS) { PHALCON_GET_HVALUE(annotation); PHALCON_CALL_METHOD(NULL, this_ptr, "processcontrollerannotation", controller_name, annotation); zend_hash_move_forward_ex(ah1, &hp1); } } } /** * Process method annotations */ PHALCON_CALL_METHOD(&method_annotations, handler_annotations, "getmethodsannotations"); if (Z_TYPE_P(method_annotations) == IS_ARRAY) { phalcon_is_iterable(method_annotations, &ah2, &hp2, 0, 0); while (zend_hash_get_current_data_ex(ah2, (void**) &hd, &hp2) == SUCCESS) { PHALCON_GET_HKEY(method, ah2, hp2); PHALCON_GET_HVALUE(collection); if (Z_TYPE_P(collection) == IS_OBJECT) { PHALCON_CALL_METHOD(&annotations, collection, "getannotations"); phalcon_is_iterable(annotations, &ah3, &hp3, 0, 0); while (zend_hash_get_current_data_ex(ah3, (void**) &hd, &hp3) == SUCCESS) { PHALCON_GET_HVALUE(annotation); PHALCON_CALL_METHOD(NULL, this_ptr, "processactionannotation", module_name, namespace_name, controller_name, method, annotation); zend_hash_move_forward_ex(ah3, &hp3); } } zend_hash_move_forward_ex(ah2, &hp2); } } } zend_hash_move_forward_ex(ah0, &hp0); } } phalcon_update_property_bool(this_ptr, SL("_processed"), 1 TSRMLS_CC); } /** * Call the parent handle method() */ PHALCON_CALL_PARENT(NULL, phalcon_mvc_router_annotations_ce, this_ptr, "handle", real_uri); PHALCON_MM_RESTORE(); }
/** * Reconfigure the route adding a new pattern and a set of paths * * @param string $pattern * @param array $paths */ PHP_METHOD(Phalcon_Mvc_Router_Route, reConfigure){ zval *pattern, *paths = NULL, *module_name = NULL, *controller_name = NULL; zval *action_name = NULL, *parts, *number_parts, *route_paths = NULL; zval *real_class_name = NULL, *namespace_name, *lower_name; zval *pcre_pattern = NULL, *compiled_pattern = NULL; PHALCON_MM_GROW(); phalcon_fetch_params(1, 1, 1, &pattern, &paths); if (!paths) { PHALCON_INIT_VAR(paths); } if (Z_TYPE_P(pattern) != IS_STRING) { PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_router_exception_ce, "The pattern must be string"); return; } if (Z_TYPE_P(paths) != IS_NULL) { if (Z_TYPE_P(paths) == IS_STRING) { PHALCON_INIT_VAR(module_name); PHALCON_INIT_VAR(controller_name); PHALCON_INIT_VAR(action_name); /** * Explode the short paths using the :: separator */ PHALCON_INIT_VAR(parts); phalcon_fast_explode_str(parts, SL("::"), paths); PHALCON_INIT_VAR(number_parts); phalcon_fast_count(number_parts, parts TSRMLS_CC); /** * Create the array paths dynamically */ switch (phalcon_get_intval(number_parts)) { case 3: PHALCON_OBS_NVAR(module_name); phalcon_array_fetch_long(&module_name, parts, 0, PH_NOISY); PHALCON_OBS_NVAR(controller_name); phalcon_array_fetch_long(&controller_name, parts, 1, PH_NOISY); PHALCON_OBS_NVAR(action_name); phalcon_array_fetch_long(&action_name, parts, 2, PH_NOISY); break; case 2: PHALCON_OBS_NVAR(controller_name); phalcon_array_fetch_long(&controller_name, parts, 0, PH_NOISY); PHALCON_OBS_NVAR(action_name); phalcon_array_fetch_long(&action_name, parts, 1, PH_NOISY); break; case 1: PHALCON_OBS_NVAR(controller_name); phalcon_array_fetch_long(&controller_name, parts, 0, PH_NOISY); break; } PHALCON_INIT_VAR(route_paths); array_init(route_paths); /** * Process module name */ if (Z_TYPE_P(module_name) != IS_NULL) { phalcon_array_update_string(&route_paths, SL("module"), &module_name, PH_COPY | PH_SEPARATE); } /** * Process controller name */ if (Z_TYPE_P(controller_name) != IS_NULL) { /** * Check if we need to obtain the namespace */ if (phalcon_memnstr_str(controller_name, SL("\\"))) { /** * Extract the real class name from the namespaced class */ PHALCON_INIT_VAR(real_class_name); phalcon_get_class_ns(real_class_name, controller_name, 0 TSRMLS_CC); /** * Extract the namespace from the namespaced class */ PHALCON_INIT_VAR(namespace_name); phalcon_get_ns_class(namespace_name, controller_name, 0 TSRMLS_CC); /** * Update the namespace */ if (zend_is_true(namespace_name)) { phalcon_array_update_string(&route_paths, SL("namespace"), &namespace_name, PH_COPY | PH_SEPARATE); } } else { PHALCON_CPY_WRT(real_class_name, controller_name); } /** * Always pass the controller to lowercase */ PHALCON_INIT_VAR(lower_name); phalcon_uncamelize(lower_name, real_class_name); /** * Update the controller path */ phalcon_array_update_string(&route_paths, SL("controller"), &lower_name, PH_COPY | PH_SEPARATE); } /** * Process action name */ if (Z_TYPE_P(action_name) != IS_NULL) { phalcon_array_update_string(&route_paths, SL("action"), &action_name, PH_COPY | PH_SEPARATE); } } else { PHALCON_CPY_WRT(route_paths, paths); } } else { PHALCON_INIT_NVAR(route_paths); array_init(route_paths); } if (Z_TYPE_P(route_paths) != IS_ARRAY) { PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_router_exception_ce, "The route contains invalid paths"); return; } /** * If the route starts with '#' we assume that it is a regular expression */ if (!phalcon_start_with_str(pattern, SL("#"))) { if (phalcon_memnstr_str(pattern, SL("{"))) { /** * The route has named parameters so we need to extract them */ PHALCON_INIT_VAR(pcre_pattern); phalcon_extract_named_params(pcre_pattern, pattern, route_paths); } else { PHALCON_CPY_WRT(pcre_pattern, pattern); } /** * Transform the route's pattern to a regular expression */ PHALCON_INIT_VAR(compiled_pattern); phalcon_call_method_p1(compiled_pattern, this_ptr, "compilepattern", pcre_pattern); } else { PHALCON_CPY_WRT(compiled_pattern, pattern); } /** * Update the original pattern */ phalcon_update_property_this(this_ptr, SL("_pattern"), pattern TSRMLS_CC); /** * Update the compiled pattern */ phalcon_update_property_this(this_ptr, SL("_compiledPattern"), compiled_pattern TSRMLS_CC); /** * Update the route's paths */ phalcon_update_property_this(this_ptr, SL("_paths"), route_paths TSRMLS_CC); PHALCON_MM_RESTORE(); }