Esempio n. 1
0
/**
 * Loads a model throwing an exception if it doesn't exist
 *
 * @return Phalcon\Mvc\Model
 */
PHP_METHOD(Phalcon_Mvc_Model_Manager, load){

	zval *model_name, *model, *exception_message;
	zend_class_entry *ce0;

	PHALCON_MM_GROW();

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &model_name) == FAILURE) {
		PHALCON_MM_RESTORE();
		RETURN_NULL();
	}

	if (phalcon_class_exists(model_name TSRMLS_CC)) {
		ce0 = phalcon_fetch_class(model_name TSRMLS_CC);
		PHALCON_INIT_VAR(model);
		object_init_ex(model, ce0);
		PHALCON_CALL_METHOD_NORETURN(model, "__construct", PH_CHECK);
		
		RETURN_CTOR(model);
	}
	
	PHALCON_INIT_VAR(exception_message);
	PHALCON_CONCAT_SVS(exception_message, "The model '", model_name, "' could not be loaded");
	PHALCON_THROW_EXCEPTION_ZVAL(phalcon_mvc_model_exception_ce, exception_message);
	return;
}
Esempio n. 2
0
/**
 * Resolves the service based on its configuration
 *
 * @param string $name
 * @param array $parameters
 * @return mixed
 */
PHP_METHOD(Phalcon_DI, get){

	zval *name, *parameters = NULL, *services, *service, *instance = NULL;
	zval *exception_message;

	PHALCON_MM_GROW();

	phalcon_fetch_params(1, 1, 1, &name, &parameters);
	
	if (!parameters) {
		PHALCON_INIT_VAR(parameters);
	}
	
	/** 
	 * A valid service alias is a string
	 */
	if (Z_TYPE_P(name) != IS_STRING) {
		PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service alias must be a string");
		return;
	}
	
	PHALCON_OBS_VAR(services);
	phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC);
	if (phalcon_array_isset(services, name)) {
		/** 
		 * The service is registered in the DI
		 */
		PHALCON_OBS_VAR(service);
		phalcon_array_fetch(&service, services, name, PH_NOISY);
	
		PHALCON_INIT_VAR(instance);
		phalcon_call_method_p2(instance, service, "resolve", parameters, this_ptr);
	} else {
		/** 
		 * The DI also acts as builder for any class even if it isn't defined in the DI
		 */
		if (phalcon_class_exists(name, 1 TSRMLS_CC)) {
			if (Z_TYPE_P(parameters) == IS_ARRAY) { 
				if (phalcon_fast_count_ev(parameters TSRMLS_CC)) {
					PHALCON_INIT_NVAR(instance);
					if (phalcon_create_instance_params(instance, name, parameters TSRMLS_CC) == FAILURE) {
						return;
					}
				} else {
					PHALCON_INIT_NVAR(instance);
					if (phalcon_create_instance(instance, name TSRMLS_CC) == FAILURE) {
						return;
					}
				}
			} else {
				PHALCON_INIT_NVAR(instance);
				if (phalcon_create_instance(instance, name TSRMLS_CC) == FAILURE) {
					return;
				}
			}
		} else {
			PHALCON_INIT_VAR(exception_message);
			PHALCON_CONCAT_SVS(exception_message, "Service '", name, "' wasn't found in the dependency injection container");
			PHALCON_THROW_EXCEPTION_ZVAL(phalcon_di_exception_ce, exception_message);
			return;
		}
	}
	
	/** 
	 * Pass the DI itself if the instance implements Phalcon\DI\InjectionAwareInterface
	 */
	if (Z_TYPE_P(instance) == IS_OBJECT) {
		if (phalcon_method_exists_ex(instance, SS("setdi") TSRMLS_CC) == SUCCESS) {
			phalcon_call_method_p1_noret(instance, "setdi", this_ptr);
		}
	}
	
	RETURN_CCTOR(instance);
}
Esempio n. 3
0
/**
 * Resolves the service
 *
 * @param array $parameters
 * @param Phalcon\DiInterface $dependencyInjector
 * @return mixed
 */
PHP_METHOD(Phalcon_DI_Service, resolve){

	zval *parameters = NULL, *dependency_injector = NULL, *shared;
	zval *shared_instance, *found = NULL, *instance = NULL, *definition;
	zval *builder, *name, *exception_message;

	PHALCON_MM_GROW();

	phalcon_fetch_params(1, 0, 2, &parameters, &dependency_injector);
	
	if (!parameters) {
		PHALCON_INIT_VAR(parameters);
	}
	
	if (!dependency_injector) {
		PHALCON_INIT_VAR(dependency_injector);
	}
	
	PHALCON_OBS_VAR(shared);
	phalcon_read_property_this(&shared, this_ptr, SL("_shared"), PH_NOISY_CC);
	
	/** 
	 * Check if the service is shared
	 */
	if (zend_is_true(shared)) {
	
		PHALCON_OBS_VAR(shared_instance);
		phalcon_read_property_this(&shared_instance, this_ptr, SL("_sharedInstance"), PH_NOISY_CC);
		if (Z_TYPE_P(shared_instance) != IS_NULL) {
			RETURN_CCTOR(shared_instance);
		}
	}
	
	PHALCON_INIT_VAR(found);
	ZVAL_BOOL(found, 1);
	
	PHALCON_INIT_VAR(instance);
	
	PHALCON_OBS_VAR(definition);
	phalcon_read_property_this(&definition, this_ptr, SL("_definition"), PH_NOISY_CC);
	if (Z_TYPE_P(definition) == IS_STRING) {
	
		/** 
		 * String definitions can be class names without implicit parameters
		 */
		if (phalcon_class_exists(definition, 1 TSRMLS_CC)) {
			if (Z_TYPE_P(parameters) == IS_ARRAY) { 
				if (phalcon_fast_count_ev(parameters TSRMLS_CC)) {
					if (phalcon_create_instance_params(instance, definition, parameters TSRMLS_CC) == FAILURE) {
						return;
					}
				} else {
					PHALCON_INIT_NVAR(instance);
					if (phalcon_create_instance(instance, definition TSRMLS_CC) == FAILURE) {
						return;
					}
				}
			} else {
				PHALCON_INIT_NVAR(instance);
				if (phalcon_create_instance(instance, definition TSRMLS_CC) == FAILURE) {
					return;
				}
			}
		} else {
			ZVAL_BOOL(found, 0);
		}
	} else {
		/** 
		 * Object definitions can be a Closure or an already resolved instance
		 */
		if (likely(Z_TYPE_P(definition) == IS_OBJECT)) {
			if (phalcon_is_instance_of(definition, SL("Closure") TSRMLS_CC)) {
				if (Z_TYPE_P(parameters) == IS_ARRAY) { 
					PHALCON_INIT_NVAR(instance);
					PHALCON_CALL_USER_FUNC_ARRAY(instance, definition, parameters);
				} else {
					PHALCON_INIT_NVAR(instance);
					PHALCON_CALL_USER_FUNC(instance, definition);
				}
			} else {
				PHALCON_CPY_WRT(instance, definition);
			}
		} else {
			/** 
			 * Array definitions require a 'className' parameter
			 */
			if (Z_TYPE_P(definition) == IS_ARRAY) { 
				PHALCON_INIT_VAR(builder);
				object_init_ex(builder, phalcon_di_service_builder_ce);
	
				PHALCON_INIT_NVAR(instance);
				phalcon_call_method_p3(instance, builder, "build", dependency_injector, definition, parameters);
			} else {
				PHALCON_INIT_NVAR(found);
				ZVAL_BOOL(found, 0);
			}
		}
	}
	
	/** 
	 * If the service can't be built, we must throw an exception
	 */
	if (PHALCON_IS_FALSE(found)) {
		PHALCON_OBS_VAR(name);
		phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC);
	
		PHALCON_INIT_VAR(exception_message);
		PHALCON_CONCAT_SVS(exception_message, "Service '", name, "' cannot be resolved");
		PHALCON_THROW_EXCEPTION_ZVAL(phalcon_di_exception_ce, exception_message);
		return;
	}
	
	/** 
	 * Update the shared instance if the service is shared
	 */
	if (zend_is_true(shared)) {
		phalcon_update_property_this(this_ptr, SL("_sharedInstance"), instance TSRMLS_CC);
	}
	
	RETURN_CCTOR(instance);
}
Esempio n. 4
0
PHP_METHOD(Phalcon_Http_Client_Adapter_Curl, sendInternal){

	zval *uri = NULL, *url = NULL, *method, *useragent, *data, *type, *files, *timeout, *curl, *username, *password, *authtype;
	zval *file = NULL, *body, *uniqid = NULL, *boundary, *key = NULL, *value = NULL;
	zval *path_parts = NULL, *filename, *basename, *filedata = NULL;
	zval *constant, *header, *headers = NULL;
	zval *content = NULL, *errorno = NULL, *error = NULL, *headersize = NULL, *httpcode = NULL, *headerstr, *bodystr, *response, *tmp = NULL;
	zend_class_entry *curlfile_ce;
	HashTable *ah0, *ah1;
	HashPosition hp0, hp1;
	zval **hd;

	PHALCON_MM_GROW();

	PHALCON_CALL_SELF(&uri, "geturi");
	PHALCON_CALL_METHOD(&url, uri, "build");

	method = phalcon_fetch_nproperty_this(this_ptr, SL("_method"), PH_NOISY TSRMLS_CC);
	useragent = phalcon_fetch_nproperty_this(this_ptr, SL("_useragent"), PH_NOISY TSRMLS_CC);
	data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC);
	type = phalcon_fetch_nproperty_this(this_ptr, SL("_type"), PH_NOISY TSRMLS_CC);
	files = phalcon_fetch_nproperty_this(this_ptr, SL("_files"), PH_NOISY TSRMLS_CC);
	timeout = phalcon_fetch_nproperty_this(this_ptr, SL("_timeout"), PH_NOISY TSRMLS_CC);
	curl = phalcon_fetch_nproperty_this(this_ptr, SL("_curl"), PH_NOISY TSRMLS_CC);
	username = phalcon_fetch_nproperty_this(this_ptr, SL("_username"), PH_NOISY TSRMLS_CC);
	password = phalcon_fetch_nproperty_this(this_ptr, SL("_password"), PH_NOISY TSRMLS_CC);
	authtype = phalcon_fetch_nproperty_this(this_ptr, SL("_authtype"), PH_NOISY TSRMLS_CC);

	PHALCON_INIT_VAR(constant);
	if (!zend_get_constant(SL("CURLOPT_URL"), constant TSRMLS_CC)) {
		RETURN_MM_FALSE;
	}

	PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, url);

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLOPT_CONNECTTIMEOUT"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, timeout);
	}

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLOPT_TIMEOUT"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, timeout);
	}

	PHALCON_INIT_NVAR(constant);
	if (PHALCON_IS_NOT_EMPTY(method) && zend_get_constant(SL("CURLOPT_CUSTOMREQUEST"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, method);
	}

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLOPT_USERAGENT"), constant TSRMLS_CC) && PHALCON_IS_NOT_EMPTY(useragent)) {
		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, useragent);
	}

	header = phalcon_fetch_nproperty_this(this_ptr, SL("_header"), PH_NOISY TSRMLS_CC);

	if (PHALCON_IS_NOT_EMPTY(username)) {
		if (PHALCON_IS_STRING(authtype, "any")) {
			PHALCON_INIT_NVAR(constant);
			PHALCON_INIT_NVAR(tmp);
			if (zend_get_constant(SL("CURLOPT_HTTPAUTH"), constant TSRMLS_CC) && zend_get_constant(SL("CURLAUTH_ANY"), tmp TSRMLS_CC)) {
				PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);

				PHALCON_INIT_NVAR(constant);
				if (zend_get_constant(SL("CURLOPT_USERPWD"), constant TSRMLS_CC)) {
					PHALCON_INIT_NVAR(tmp);
					PHALCON_CONCAT_VSV(tmp, username, ":", password);
					PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);
				}
			}
		} else if (PHALCON_IS_STRING(authtype, "basic")) {
			PHALCON_INIT_NVAR(constant);
			PHALCON_INIT_NVAR(tmp);
			if (zend_get_constant(SL("CURLOPT_HTTPAUTH"), constant TSRMLS_CC) && zend_get_constant(SL("CURLAUTH_BASIC"), tmp TSRMLS_CC)) {
				PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);

				PHALCON_INIT_NVAR(constant);
				if (zend_get_constant(SL("CURLOPT_USERPWD"), constant TSRMLS_CC)) {
					PHALCON_INIT_NVAR(tmp);
					PHALCON_CONCAT_VSV(tmp, username, ":", password);
					PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);
				}
			}
		} else if (PHALCON_IS_STRING(authtype, "digest")) {
			PHALCON_INIT_NVAR(constant);
			PHALCON_INIT_NVAR(tmp);
			if (zend_get_constant(SL("CURLOPT_HTTPAUTH"), constant TSRMLS_CC) && zend_get_constant(SL("CURLAUTH_DIGEST"), tmp TSRMLS_CC)) {
				PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);

				PHALCON_INIT_NVAR(constant);
				if (zend_get_constant(SL("CURLOPT_USERPWD"), constant TSRMLS_CC)) {
					PHALCON_INIT_NVAR(tmp);
					PHALCON_CONCAT_VSV(tmp, username, ":", password);
					PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, tmp);
				}
			}
		}
	}

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLOPT_SAFE_UPLOAD"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, PHALCON_GLOBAL(z_true));
	}

	if (Z_TYPE_P(data) == IS_STRING && PHALCON_IS_NOT_EMPTY(data)) {
		PHALCON_INIT_NVAR(key);
		ZVAL_STRING(key, "Content-Type", 1);

		if (PHALCON_IS_EMPTY(type)) {
			PHALCON_INIT_NVAR(type);
			ZVAL_STRING(type, "application/x-www-form-urlencoded", 1);
		}

		PHALCON_CALL_METHOD(NULL, header, "set", key, type);

		PHALCON_INIT_NVAR(constant);
		zend_get_constant(SL("CURLOPT_POSTFIELDS"), constant TSRMLS_CC);

		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, data);
	} else if (phalcon_class_exists(SL("CURLFile"), 0 TSRMLS_CC)) {
		if (Z_TYPE_P(data) != IS_ARRAY) {
			PHALCON_INIT_NVAR(data);
			array_init(data);
		}

		if (Z_TYPE_P(files) == IS_ARRAY) {
			phalcon_is_iterable(files, &ah0, &hp0, 0, 0);
			while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {
				PHALCON_GET_HVALUE(file);

				if (PHALCON_IS_NOT_EMPTY(file)) {
					curlfile_ce = zend_fetch_class(SL("CURLFile"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC);

					PHALCON_INIT_NVAR(tmp);
					object_init_ex(tmp, curlfile_ce);
					PHALCON_CALL_METHOD(NULL, tmp, "__construct", file);

					phalcon_array_append(&data, tmp, PH_COPY);
				}

				zend_hash_move_forward_ex(ah0, &hp0);
			}
		}

		PHALCON_INIT_NVAR(constant);
		zend_get_constant(SL("CURLOPT_POSTFIELDS"), constant TSRMLS_CC);

		PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, data);
	} else {
		PHALCON_CALL_FUNCTION(&uniqid, "uniqid");

		PHALCON_INIT_VAR(boundary);
		PHALCON_CONCAT_SV(boundary, "--------------", uniqid);

		PHALCON_INIT_VAR(body);

		if (Z_TYPE_P(data) == IS_ARRAY) {
			phalcon_is_iterable(data, &ah0, &hp0, 0, 0);
			while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {
				PHALCON_GET_HKEY(key, ah0, hp0);
				PHALCON_GET_HVALUE(value);

				PHALCON_SCONCAT_SVS(body, "--", boundary, "\r\n");
				PHALCON_SCONCAT_SVSVS(body, "Content-Disposition: form-data; name=\"", key, "\"\r\n\r\n", value, "\r\n");

				zend_hash_move_forward_ex(ah0, &hp0);
			}
		}


		if (Z_TYPE_P(files) == IS_ARRAY) {
			phalcon_is_iterable(files, &ah1, &hp1, 0, 0);
			while (zend_hash_get_current_data_ex(ah1, (void**) &hd, &hp1) == SUCCESS) {
				PHALCON_GET_HVALUE(file);

				if (PHALCON_IS_NOT_EMPTY(file)) {
					PHALCON_CALL_FUNCTION(&path_parts, "pathinfo", file);

					if (phalcon_array_isset_string_fetch(&filename, path_parts, SS("filename")) && phalcon_array_isset_string_fetch(&basename, path_parts, SS("basename"))) {
						PHALCON_CALL_FUNCTION(&filedata, "file_get_contents", file);

						PHALCON_SCONCAT_SVS(body, "--", boundary, "\r\n");
						PHALCON_SCONCAT_SVSVS(body, "Content-Disposition: form-data; name=\"", filename, "\"; filename=\"", basename, "\"\r\n");
						PHALCON_SCONCAT_SVS(body, "Content-Type: application/octet-stream\r\n\r\n", filedata, "\r\n");
					}
				}

				zend_hash_move_forward_ex(ah1, &hp1);
			}
		}

		if (!PHALCON_IS_EMPTY(body)) {
			PHALCON_SCONCAT_SVS(body, "--", boundary, "--\r\n");

			PHALCON_INIT_NVAR(key);
			ZVAL_STRING(key, "Content-Type", 1);

			PHALCON_INIT_NVAR(value);
			PHALCON_CONCAT_SV(value, "multipart/form-data; boundary=", boundary);

			PHALCON_CALL_METHOD(NULL, header, "set", key, value);

			PHALCON_INIT_NVAR(key);
			ZVAL_STRING(key, "Content-Length", 1);		

			PHALCON_INIT_NVAR(value);
			ZVAL_LONG(value, Z_STRLEN_P(body));

			PHALCON_CALL_METHOD(NULL, header, "set", key, value);

			PHALCON_CALL_METHOD(&headers, header, "build");

			PHALCON_INIT_NVAR(constant);
			zend_get_constant(SL("CURLOPT_POSTFIELDS"), constant TSRMLS_CC);

			PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, body);

			PHALCON_INIT_NVAR(constant);
			zend_get_constant(SL("CURLOPT_HTTPHEADER"), constant TSRMLS_CC);

			PHALCON_CALL_FUNCTION(NULL, "curl_setopt", curl, constant, headers);
		}
	}

	PHALCON_CALL_FUNCTION(&content, "curl_exec", curl);
	PHALCON_CALL_FUNCTION(&errorno, "curl_errno", curl);

	if (PHALCON_IS_TRUE(errorno)) {
		PHALCON_CALL_FUNCTION(&error, "curl_error", curl);

		PHALCON_THROW_EXCEPTION_ZVAL(phalcon_http_client_exception_ce, error);
		return;
	}

	PHALCON_INIT_VAR(response);
	object_init_ex(response, phalcon_http_client_response_ce);
	PHALCON_CALL_METHOD(NULL, response, "__construct");

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLINFO_HTTP_CODE"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(&httpcode, "curl_getinfo", curl, constant);
		PHALCON_CALL_METHOD(NULL, response, "setstatuscode", httpcode);
	}

	PHALCON_INIT_NVAR(constant);
	if (zend_get_constant(SL("CURLINFO_HEADER_SIZE"), constant TSRMLS_CC)) {
		PHALCON_CALL_FUNCTION(&headersize, "curl_getinfo", curl, constant);

		PHALCON_INIT_VAR(headerstr);
		phalcon_substr(headerstr, content, 0 , Z_LVAL_P(headersize));

		PHALCON_INIT_VAR(bodystr);
		phalcon_substr(bodystr, content, Z_LVAL_P(headersize) , Z_STRLEN_P(content));

		PHALCON_CALL_METHOD(NULL, response, "setheader", headerstr);
		PHALCON_CALL_METHOD(NULL, response, "setbody", bodystr);
	}

	RETURN_CTOR(response);
}
Esempio n. 5
0
/**
 * Handles a MVC request
 *
 * @param string $uri
 * @return Phalcon\Http\ResponseInterface
 */
PHP_METHOD(Phalcon_Mvc_Application, handle){

	zval *uri = NULL, *dependency_injector, *events_manager;
	zval *event_name = NULL, *status = NULL, *service = NULL, *router, *module_name = NULL;
	zval *module_object = NULL, *modules, *exception_msg = NULL;
	zval *module, *class_name = NULL, *path, *module_params;
	zval *implicit_view, *view, *namespace_name;
	zval *controller_name = NULL, *action_name = NULL, *params = NULL;
	zval *dispatcher, *controller, *returned_response = NULL;
	zval *possible_response, *render_status = NULL, *response = NULL;
	zval *content;

	PHALCON_MM_GROW();

	phalcon_fetch_params(1, 0, 1, &uri);
	
	if (!uri) {
		PHALCON_INIT_VAR(uri);
	}
	
	PHALCON_OBS_VAR(dependency_injector);
	phalcon_read_property_this(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC);
	if (Z_TYPE_P(dependency_injector) != IS_OBJECT) {
		PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_application_exception_ce, "A dependency injection object is required to access internal services");
		return;
	}
	
	PHALCON_OBS_VAR(events_manager);
	phalcon_read_property_this(&events_manager, this_ptr, SL("_eventsManager"), PH_NOISY_CC);
	
	/** 
	 * Call boot event, this allow the developer to perform initialization actions
	 */
	if (Z_TYPE_P(events_manager) == IS_OBJECT) {
	
		PHALCON_INIT_VAR(event_name);
		ZVAL_STRING(event_name, "application:boot", 1);
	
		PHALCON_INIT_VAR(status);
		phalcon_call_method_p2(status, events_manager, "fire", event_name, this_ptr);
		if (PHALCON_IS_FALSE(status)) {
			RETURN_MM_FALSE;
		}
	}
	
	PHALCON_INIT_VAR(service);
	ZVAL_STRING(service, "router", 1);
	
	PHALCON_INIT_VAR(router);
	phalcon_call_method_p1(router, dependency_injector, "getshared", service);
	
	/** 
	 * Handle the URI pattern (if any)
	 */
	phalcon_call_method_p1_noret(router, "handle", uri);
	
	/** 
	 * Load module config
	 */
	PHALCON_INIT_VAR(module_name);
	phalcon_call_method(module_name, router, "getmodulename");
	
	/** 
	 * If the router doesn't return a valid module we use the default module
	 */
	if (!zend_is_true(module_name)) {
		PHALCON_OBS_NVAR(module_name);
		phalcon_read_property_this(&module_name, this_ptr, SL("_defaultModule"), PH_NOISY_CC);
	}
	
	PHALCON_INIT_VAR(module_object);
	
	/** 
	 * Process the module definition
	 */
	if (zend_is_true(module_name)) {
		if (Z_TYPE_P(events_manager) == IS_OBJECT) {
	
			PHALCON_INIT_NVAR(event_name);
			ZVAL_STRING(event_name, "application:beforeStartModule", 1);
	
			PHALCON_INIT_NVAR(status);
			phalcon_call_method_p3(status, events_manager, "fire", event_name, this_ptr, module_name);
			if (PHALCON_IS_FALSE(status)) {
				RETURN_MM_FALSE;
			}
		}
	
		/** 
		 * Check if the module passed by the router is registered in the modules container
		 */
		PHALCON_OBS_VAR(modules);
		phalcon_read_property_this(&modules, this_ptr, SL("_modules"), PH_NOISY_CC);
		if (!phalcon_array_isset(modules, module_name)) {
			PHALCON_INIT_VAR(exception_msg);
			PHALCON_CONCAT_SVS(exception_msg, "Module '", module_name, "' isn't registered in the application container");
			PHALCON_THROW_EXCEPTION_ZVAL(phalcon_mvc_application_exception_ce, exception_msg);
			return;
		}
	
		/** 
		 * A module definition must ne an array or an object
		 */
		PHALCON_OBS_VAR(module);
		phalcon_array_fetch(&module, modules, module_name, PH_NOISY);
		if (Z_TYPE_P(module) != IS_ARRAY) { 
			if (Z_TYPE_P(module) != IS_OBJECT) {
				PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_application_exception_ce, "Invalid module definition");
				return;
			}
		}
	
		/** 
		 * An array module definition contains a path to a module definition class
		 */
		if (Z_TYPE_P(module) == IS_ARRAY) { 
	
			/** 
			 * Class name used to load the module definition
			 */
			if (phalcon_array_isset_string(module, SS("className"))) {
				PHALCON_OBS_VAR(class_name);
				phalcon_array_fetch_string(&class_name, module, SL("className"), PH_NOISY);
			} else {
				PHALCON_INIT_NVAR(class_name);
				ZVAL_STRING(class_name, "Module", 1);
			}
	
			/** 
			 * If developer specify a path try to include the file
			 */
			if (phalcon_array_isset_string(module, SS("path"))) {
	
				PHALCON_OBS_VAR(path);
				phalcon_array_fetch_string(&path, module, SL("path"), PH_NOISY);
				if (!phalcon_class_exists(class_name, 0 TSRMLS_CC)) {
					if (phalcon_file_exists(path TSRMLS_CC) == SUCCESS) {
						if (phalcon_require(path TSRMLS_CC) == FAILURE) {
							return;
						}
					} else {
						PHALCON_INIT_NVAR(exception_msg);
						PHALCON_CONCAT_SVS(exception_msg, "Module definition path '", path, "' doesn't exist");
						PHALCON_THROW_EXCEPTION_ZVAL(phalcon_mvc_application_exception_ce, exception_msg);
						return;
					}
				}
			}
	
			phalcon_call_method_p1(module_object, dependency_injector, "get", class_name);
	
			/** 
			 * 'registerAutoloaders' and 'registerServices' are automatically called
			 */
			phalcon_call_method_p1_noret(module_object, "registerautoloaders", dependency_injector);
			phalcon_call_method_p1_noret(module_object, "registerservices", dependency_injector);
		} else {
			/** 
			 * A module definition object, can be a Closure instance
			 */
			if (phalcon_is_instance_of(module, SL("Closure") TSRMLS_CC)) {
				PHALCON_INIT_VAR(module_params);
				array_init_size(module_params, 1);
				phalcon_array_append(&module_params, dependency_injector, PH_SEPARATE);
	
				PHALCON_INIT_NVAR(status);
				PHALCON_CALL_USER_FUNC_ARRAY(status, module, module_params);
			} else {
				PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_application_exception_ce, "Invalid module definition");
				return;
			}
		}
	
		/** 
		 * Calling afterStartModule event
		 */
		if (Z_TYPE_P(events_manager) == IS_OBJECT) {
			phalcon_update_property_this(this_ptr, SL("_moduleObject"), module_object TSRMLS_CC);
	
			PHALCON_INIT_NVAR(event_name);
			ZVAL_STRING(event_name, "application:afterStartModule", 1);
	
			PHALCON_INIT_NVAR(status);
			phalcon_call_method_p3(status, events_manager, "fire", event_name, this_ptr, module_name);
			if (PHALCON_IS_FALSE(status)) {
				RETURN_MM_FALSE;
			}
		}
	}
	
	/** 
	 * Check whether use implicit views or not
	 */
	PHALCON_OBS_VAR(implicit_view);
	phalcon_read_property_this(&implicit_view, this_ptr, SL("_implicitView"), PH_NOISY_CC);
	if (PHALCON_IS_TRUE(implicit_view)) {
		PHALCON_INIT_NVAR(service);
		ZVAL_STRING(service, "view", 1);
	
		PHALCON_INIT_VAR(view);
		phalcon_call_method_p1(view, dependency_injector, "getshared", service);
	}
	
	/** 
	 * We get the parameters from the router and assign them to the dispatcher
	 */
	PHALCON_INIT_NVAR(module_name);
	phalcon_call_method(module_name, router, "getmodulename");
	
	PHALCON_INIT_VAR(namespace_name);
	phalcon_call_method(namespace_name, router, "getnamespacename");
	
	PHALCON_INIT_VAR(controller_name);
	phalcon_call_method(controller_name, router, "getcontrollername");
	
	PHALCON_INIT_VAR(action_name);
	phalcon_call_method(action_name, router, "getactionname");
	
	PHALCON_INIT_VAR(params);
	phalcon_call_method(params, router, "getparams");
	
	PHALCON_INIT_NVAR(service);
	ZVAL_STRING(service, "dispatcher", 1);
	
	PHALCON_INIT_VAR(dispatcher);
	phalcon_call_method_p1(dispatcher, dependency_injector, "getshared", service);
	
	/** 
	 * Assign the values passed from the router
	 */
	phalcon_call_method_p1_noret(dispatcher, "setmodulename", module_name);
	phalcon_call_method_p1_noret(dispatcher, "setnamespacename", namespace_name);
	phalcon_call_method_p1_noret(dispatcher, "setcontrollername", controller_name);
	phalcon_call_method_p1_noret(dispatcher, "setactionname", action_name);
	phalcon_call_method_p1_noret(dispatcher, "setparams", params);
	
	/** 
	 * Start the view component (start output buffering)
	 */
	if (PHALCON_IS_TRUE(implicit_view)) {
		phalcon_call_method_noret(view, "start");
	}
	
	/** 
	 * Calling beforeHandleRequest
	 */
	if (Z_TYPE_P(events_manager) == IS_OBJECT) {
	
		PHALCON_INIT_NVAR(event_name);
		ZVAL_STRING(event_name, "application:beforeHandleRequest", 1);
	
		PHALCON_INIT_NVAR(status);
		phalcon_call_method_p3(status, events_manager, "fire", event_name, this_ptr, dispatcher);
		if (PHALCON_IS_FALSE(status)) {
			RETURN_MM_FALSE;
		}
	}
	
	/** 
	 * The dispatcher must return an object
	 */
	PHALCON_INIT_VAR(controller);
	phalcon_call_method(controller, dispatcher, "dispatch");
	
	PHALCON_INIT_VAR(returned_response);
	ZVAL_BOOL(returned_response, 0);
	
	/** 
	 * Get the latest value returned by an action
	 */
	PHALCON_INIT_VAR(possible_response);
	phalcon_call_method(possible_response, dispatcher, "getreturnedvalue");
	if (Z_TYPE_P(possible_response) == IS_OBJECT) {
		/** 
		 * Check if the returned object is already a response
		 */
		phalcon_instance_of(returned_response, possible_response, phalcon_http_responseinterface_ce TSRMLS_CC);
	}
	
	/** 
	 * Calling afterHandleRequest
	 */
	if (Z_TYPE_P(events_manager) == IS_OBJECT) {
		PHALCON_INIT_NVAR(event_name);
		ZVAL_STRING(event_name, "application:afterHandleRequest", 1);
		phalcon_call_method_p3_noret(events_manager, "fire", event_name, this_ptr, controller);
	}
	
	/** 
	 * If the dispatcher returns an object we try to render the view in auto-rendering
	 * mode
	 */
	if (PHALCON_IS_FALSE(returned_response)) {
		if (PHALCON_IS_TRUE(implicit_view)) {
	
			if (Z_TYPE_P(controller) == IS_OBJECT) {
	
				PHALCON_INIT_VAR(render_status);
				ZVAL_BOOL(render_status, 1);
	
				/** 
				 * This allows to make a custom view render
				 */
				if (Z_TYPE_P(events_manager) == IS_OBJECT) {
					PHALCON_INIT_NVAR(event_name);
					ZVAL_STRING(event_name, "application:viewRender", 1);
	
					phalcon_call_method_p3(render_status, events_manager, "fire", event_name, this_ptr, view);
				}
	
				/** 
				 * Check if the view process has been treated by the developer
				 */
				if (PHALCON_IS_NOT_FALSE(render_status)) {
					PHALCON_INIT_NVAR(controller_name);
					phalcon_call_method(controller_name, dispatcher, "getcontrollername");
	
					PHALCON_INIT_NVAR(action_name);
					phalcon_call_method(action_name, dispatcher, "getactionname");
	
					PHALCON_INIT_NVAR(params);
					phalcon_call_method(params, dispatcher, "getparams");
	
					/** 
					 * Automatic render based on the latest controller executed
					 */
					phalcon_call_method_p3_noret(view, "render", controller_name, action_name, params);
				}
			}
		}
	}
	
	/** 
	 * Finish the view component (stop output buffering)
	 */
	if (PHALCON_IS_TRUE(implicit_view)) {
		phalcon_call_method_noret(view, "finish");
	}
	
	if (PHALCON_IS_FALSE(returned_response)) {
	
		PHALCON_INIT_NVAR(service);
		ZVAL_STRING(service, "response", 1);
	
		PHALCON_INIT_VAR(response);
		phalcon_call_method_p1(response, dependency_injector, "getshared", service);
		if (PHALCON_IS_TRUE(implicit_view)) {
			/** 
			 * The content returned by the view is passed to the response service
			 */
			PHALCON_INIT_VAR(content);
			phalcon_call_method(content, view, "getcontent");
			phalcon_call_method_p1_noret(response, "setcontent", content);
		}
	} else {
		/** 
		 * We don't need to create a response because there is a one already created
		 */
		PHALCON_CPY_WRT(response, possible_response);
	}
	
	/** 
	 * Calling beforeSendResponse
	 */
	if (Z_TYPE_P(events_manager) == IS_OBJECT) {
		PHALCON_INIT_NVAR(event_name);
		ZVAL_STRING(event_name, "application:beforeSendResponse", 1);
		phalcon_call_method_p3_noret(events_manager, "fire", event_name, this_ptr, response);
	}
	
	/** 
	 * Headers are automatically send
	 */
	phalcon_call_method_noret(response, "sendheaders");
	
	/** 
	 * Cookies are automatically send
	 */
	phalcon_call_method_noret(response, "sendcookies");
	
	/** 
	 * Return the response
	 */
	
	RETURN_CCTOR(response);
}
Esempio n. 6
0
/**
 * Handles a MVC request
 *
 * @param string $uri
 * @return Phalcon\Http\ResponseInterface
 */
PHP_METHOD(Phalcon_Mvc_JsonRpc, handle){

	zval *uri = NULL, *dependency_injector, *events_manager;
	zval *status = NULL, *service = NULL, *request = NULL, *response = NULL;
	zval *json = NULL, *data = NULL, *jsonrpc_message, *jsonrpc_error, *jsonrpc_result = NULL;
	zval *jsonrpc_method, *jsonrpc_params, *jsonrpc_id;
	zval *url = NULL, *router = NULL, *module_name = NULL;
	zval *module_object = NULL, *modules;
	zval *module, *class_name = NULL, *module_params;
	zval *namespace_name = NULL;
	zval *controller_name = NULL, *action_name = NULL, *params = NULL, *exact = NULL;
	zval *dispatcher = NULL, *controller = NULL, *returned_response = NULL;
	zval *path;

	PHALCON_MM_GROW();
	
	dependency_injector = phalcon_read_property(getThis(), SL("_dependencyInjector"), PH_NOISY);
	if (Z_TYPE_P(dependency_injector) != IS_OBJECT) {
		PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_jsonrpc_exception_ce, "A dependency injection object is required to access internal services");
		return;
	}
	
	events_manager = phalcon_read_property(getThis(), SL("_eventsManager"), PH_NOISY);
	if (Z_TYPE_P(events_manager) != IS_OBJECT) {
		events_manager = NULL;
	}
	else {
		PHALCON_VERIFY_INTERFACE_EX(events_manager, phalcon_events_managerinterface_ce, phalcon_mvc_jsonrpc_exception_ce, 1);
	}

	/* Call boot event, this allows the developer to perform initialization actions */
	if (FAILURE == phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:boot", getThis(), NULL)) {
		RETURN_MM_FALSE;
	}

	/* Deserializer Json */

	PHALCON_INIT_NVAR(service);
	ZVAL_STR(service, IS(request));
	
	PHALCON_CALL_METHOD(&request, dependency_injector, "getshared", service);
	PHALCON_VERIFY_INTERFACE(request, phalcon_http_requestinterface_ce);

	PHALCON_CALL_METHOD(&json, request, "getrawbody");
	PHALCON_CALL_FUNCTION(&data, "json_decode", json, &PHALCON_GLOBAL(z_true));


	PHALCON_INIT_NVAR(service);
	ZVAL_STR(service, IS(response));

	PHALCON_CALL_METHOD(&response, dependency_injector, "getshared", service);
	PHALCON_VERIFY_INTERFACE(response, phalcon_http_responseinterface_ce);

	PHALCON_INIT_VAR(jsonrpc_message);
	array_init(jsonrpc_message);
	
	PHALCON_INIT_VAR(jsonrpc_error);
	array_init(jsonrpc_error);

	if (PHALCON_IS_EMPTY(data)) {
		phalcon_array_update_str_long(jsonrpc_error, SL("code"), __LINE__, 0);
		phalcon_array_update_str_str(jsonrpc_error, SL("message"), SL("Parse error"), PH_COPY);
	} else if (Z_TYPE_P(data) != IS_ARRAY) {
		phalcon_array_update_str_long(jsonrpc_error, SL("code"), __LINE__, 0);
		phalcon_array_update_str_str(jsonrpc_error, SL("message"), SL("Parse error"), PH_COPY);
	} else if (!phalcon_array_isset_str(data, SL("jsonrpc"))) {		
			phalcon_array_update_str_long(jsonrpc_error, SL("code"), __LINE__, 0);
			phalcon_array_update_str_str(jsonrpc_error, SL("message"), SL("Invalid Request"), PH_COPY);
	} else if (!phalcon_array_isset_str(data, SL("method"))) {
			phalcon_array_update_str_long(jsonrpc_error, SL("code"), __LINE__, 0);
			phalcon_array_update_str_str(jsonrpc_error, SL("message"), SL("Invalid Request"), PH_COPY);
	} else {
		PHALCON_OBS_VAR(jsonrpc_method);
		phalcon_array_fetch_str(&jsonrpc_method, data, SL("method"), PH_NOISY);

		if (phalcon_array_isset_str(data, SL("params"))) {
			PHALCON_OBS_VAR(jsonrpc_params);
			phalcon_array_fetch_str(&jsonrpc_params, data, SL("params"), PH_NOISY);
		} else {
			PHALCON_INIT_VAR(jsonrpc_params);
			array_init(jsonrpc_params);
		}

		PHALCON_INIT_NVAR(service);
		ZVAL_STR(service, IS(url));
		PHALCON_CALL_METHOD(&url, dependency_injector, "getshared", service);
		PHALCON_VERIFY_INTERFACE(url, phalcon_mvc_urlinterface_ce);

		PHALCON_CALL_METHOD(&uri, url, "get", jsonrpc_method);

		PHALCON_INIT_NVAR(service);
		ZVAL_STR(service, IS(router));
		PHALCON_CALL_METHOD(&router, dependency_injector, "getshared", service);
		PHALCON_VERIFY_INTERFACE(router, phalcon_mvc_routerinterface_ce);

		/* Handle the URI pattern (if any) */
		PHALCON_CALL_METHOD(NULL, router, "handle", uri);
		
		/* Load module config */
		PHALCON_CALL_METHOD(&module_name, router, "getmodulename");

		/* Load module config */
		PHALCON_CALL_METHOD(&module_name, router, "getmodulename");
		
		/* If the router doesn't return a valid module we use the default module */
		if (!zend_is_true(module_name)) {
			module_name = phalcon_read_property(getThis(), SL("_defaultModule"), PH_NOISY);
		}
		
		/** 
		 * Process the module definition
		 */
		if (zend_is_true(module_name)) {
			if (FAILURE == phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:beforeStartModule", getThis(), module_name)) {
				RETURN_MM_FALSE;
			}

			/** 
			 * Check if the module passed by the router is registered in the modules container
			 */
			modules = phalcon_read_property(getThis(), SL("_modules"), PH_NOISY);
			if (!phalcon_array_isset_fetch(&module, modules, module_name)) {
				convert_to_string(module_name);
				zend_throw_exception_ex(phalcon_mvc_jsonrpc_exception_ce, 0, "Module %s is not registered in the jsonrpc container", Z_STRVAL_P(module_name));
				RETURN_MM();
			}
		
			/** 
			 * A module definition must be an array or an object
			 */
			if (Z_TYPE_P(module) != IS_ARRAY && Z_TYPE_P(module) != IS_OBJECT) {
				PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_jsonrpc_exception_ce, "Invalid module definition");
				return;
			}
		
			/* An array module definition contains a path to a module definition class */
			if (Z_TYPE_P(module) == IS_ARRAY) { 
				/* Class name used to load the module definition */
				if (phalcon_array_isset_str(module, SL("className"))) {
					PHALCON_OBS_VAR(class_name);
					phalcon_array_fetch_str(&class_name, module, SL("className"), PH_NOISY);
				} else {
					PHALCON_INIT_NVAR(class_name);
					ZVAL_STRING(class_name, "Module");
				}
		
				/* If the developer has specified a path, try to include the file */
				if (phalcon_array_isset_str(module, SL("path"))) {
		
					PHALCON_OBS_VAR(path);
					phalcon_array_fetch_str(&path, module, SL("path"), PH_NOISY);
					convert_to_string_ex(path);
					if (Z_TYPE_P(class_name) != IS_STRING || phalcon_class_exists(class_name, 0) == NULL) {
						if (phalcon_file_exists(path) == SUCCESS) {
							RETURN_MM_ON_FAILURE(phalcon_require(Z_STRVAL_P(path)));
						} else {
							zend_throw_exception_ex(phalcon_mvc_jsonrpc_exception_ce, 0, "Module definition path '%s' does not exist", Z_STRVAL_P(path));
							RETURN_MM();
						}
					}
				}
		
				PHALCON_CALL_METHOD(&module_object, dependency_injector, "get", class_name);
		
				/** 
				 * 'registerAutoloaders' and 'registerServices' are automatically called
				 */
				PHALCON_CALL_METHOD(NULL, module_object, "registerautoloaders", dependency_injector);
				PHALCON_CALL_METHOD(NULL, module_object, "registerservices", dependency_injector);
			} else if (Z_TYPE_P(module) == IS_OBJECT && instanceof_function(Z_OBJCE_P(module), zend_ce_closure)) {
				/* A module definition object, can be a Closure instance */
				PHALCON_INIT_VAR(module_params);
				array_init_size(module_params, 1);
				phalcon_array_append(module_params, dependency_injector, PH_COPY);

				PHALCON_CALL_USER_FUNC_ARRAY(&status, module, module_params);
			} else {
				PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_jsonrpc_exception_ce, "Invalid module definition");
				return;
			}
		
			/* Calling afterStartModule event */
			if (events_manager) {
				if (!module_object) {
					module_object = &PHALCON_GLOBAL(z_null);
				}

				phalcon_update_property_this(getThis(), SL("_moduleObject"), module_object);
				if (FAILURE == phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:afterStartModule", getThis(), module_name)) {
					RETURN_MM_FALSE;
				}
			}
		}
		
		/* We get the parameters from the router and assign them to the dispatcher */
		PHALCON_CALL_METHOD(&module_name, router, "getmodulename");
		PHALCON_CALL_METHOD(&namespace_name, router, "getnamespacename");
		PHALCON_CALL_METHOD(&controller_name, router, "getcontrollername");
		PHALCON_CALL_METHOD(&action_name, router, "getactionname");
		PHALCON_CALL_METHOD(&params, router, "getparams");
		PHALCON_CALL_METHOD(&exact, router, "isexactcontrollername");

		PHALCON_INIT_NVAR(service);
		ZVAL_STR(service, IS(dispatcher));
		
		PHALCON_CALL_METHOD(&dispatcher, dependency_injector, "getshared", service);
		PHALCON_VERIFY_INTERFACE(dispatcher, phalcon_dispatcherinterface_ce);
		
		/* Assign the values passed from the router */
		PHALCON_CALL_METHOD(NULL, dispatcher, "setmodulename", module_name);
		PHALCON_CALL_METHOD(NULL, dispatcher, "setnamespacename", namespace_name);
		PHALCON_CALL_METHOD(NULL, dispatcher, "setcontrollername", controller_name, exact);
		PHALCON_CALL_METHOD(NULL, dispatcher, "setactionname", action_name);
		PHALCON_CALL_METHOD(NULL, dispatcher, "setparams", jsonrpc_params);
		
		/* Calling beforeHandleRequest */
		RETURN_MM_ON_FAILURE(phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:beforeHandleRequest", getThis(), dispatcher));
		
		/* The dispatcher must return an object */
		PHALCON_CALL_METHOD(&controller, dispatcher, "dispatch");
		
		PHALCON_INIT_VAR(returned_response);
		
		/* Get the latest value returned by an action */
		PHALCON_CALL_METHOD(&jsonrpc_result, dispatcher, "getreturnedvalue");
	}
		
	/* Calling afterHandleRequest */
	if (FAILURE == phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:afterHandleRequest", getThis(), controller) && EG(exception)) {
		RETURN_MM();
	}
	
	phalcon_array_update_str_str(jsonrpc_message, SL("jsonrpc"), SL("2.0"), PH_COPY);

	if (PHALCON_IS_NOT_EMPTY(jsonrpc_error)) {
		phalcon_array_update_str(jsonrpc_message, SL("error"), jsonrpc_error, PH_COPY);
	}

	if (jsonrpc_result != NULL) {
		phalcon_array_update_str(jsonrpc_message, SL("result"), jsonrpc_result, PH_COPY);
	}
	
	if (phalcon_array_isset_str_fetch(&jsonrpc_id, data, SL("id"))) {
		phalcon_array_update_str(jsonrpc_message, SL("id"), jsonrpc_id, PH_COPY);
	} else {
		phalcon_array_update_str(jsonrpc_message, SL("id"), &PHALCON_GLOBAL(z_null), PH_COPY);
	}

	PHALCON_CALL_METHOD(NULL, response, "setjsoncontent", jsonrpc_message);
	

	/* Calling beforeSendResponse */
	if (FAILURE == phalcon_mvc_jsonrpc_fire_event(events_manager, "jsonrpc:beforeSendResponse", getThis(), response) && EG(exception)) {
		RETURN_MM();
	}
	
	/* Headers are automatically sent */
	PHALCON_CALL_METHOD(NULL, response, "sendheaders");
	
	/* Cookies are automatically sent */
	PHALCON_CALL_METHOD(NULL, response, "sendcookies");
	
	/* Return the response */
	RETURN_CCTOR(response);
}
Esempio n. 7
0
/**
 * Resolves the service
 *
 * @param array $parameters
 * @param Phalcon\DIInterface $dependencyInjector
 * @return object
 */
PHP_METHOD(Phalcon_DI_Service, resolve){

	zval *parameters = NULL, *dependency_injector = NULL, name = {}, shared = {}, shared_instance = {}, definition = {}, builder = {};
	int found = 0, ishared = 0;

	phalcon_fetch_params(0, 0, 2, &parameters, &dependency_injector);

	if (!parameters) {
		parameters = &PHALCON_GLOBAL(z_null);
	}

	if (!dependency_injector) {
		dependency_injector = &PHALCON_GLOBAL(z_null);
	}

	phalcon_return_property(&shared, getThis(), SL("_shared"));
	phalcon_return_property(&shared_instance, getThis(), SL("_sharedInstance"));

	ishared = zend_is_true(&shared);

	/* Check if the service is shared */
	if (ishared && Z_TYPE(shared_instance) != IS_NULL) {
		RETURN_CTORW(&shared_instance);
	}

	phalcon_return_property(&definition, getThis(), SL("_definition"));

	if (Z_TYPE(definition) == IS_STRING) {
		/* String definitions can be class names without implicit parameters */
		if (phalcon_class_exists(&definition, 1) != NULL) {
			found = 1;
			if (Z_TYPE_P(parameters) == IS_ARRAY) {
				RETURN_ON_FAILURE(phalcon_create_instance_params(return_value, &definition, parameters));
			} else {
				RETURN_ON_FAILURE(phalcon_create_instance(return_value, &definition));
			}
		}
	} else if (likely(Z_TYPE(definition) == IS_OBJECT)) {
		/* Object definitions can be a Closure or an already resolved instance */
		found = 1;
		if (instanceof_function_ex(Z_OBJCE(definition), zend_ce_closure, 0)) {
			if (likely(Z_TYPE_P(dependency_injector) == IS_OBJECT)) {
				PHALCON_CALL_CE_STATICW(&definition, zend_ce_closure, "bind", &definition, dependency_injector);
			}
			if (Z_TYPE_P(parameters) == IS_ARRAY) {
				PHALCON_CALL_USER_FUNC_ARRAYW(return_value, &definition, parameters);
			} else {
				PHALCON_CALL_USER_FUNCW(return_value, &definition);
			}
		} else {
			PHALCON_CPY_WRT(return_value, &definition);
		}
	} else if (Z_TYPE(definition) == IS_ARRAY) {
		found = 1;
		/* Array definitions require a 'className' parameter */
		object_init_ex(&builder, phalcon_di_service_builder_ce);

		PHALCON_CALL_METHODW(return_value, &builder, "build", dependency_injector, &definition, parameters);
	}

	if (!EG(exception)) {
		if (found) {
			if (ishared) {
				phalcon_update_property_zval(getThis(), SL("_sharedInstance"), return_value);
			}
			/* Update the shared instance if the service is shared */
			phalcon_update_property_bool(getThis(), SL("_resolved"), 1);
		} else {
			phalcon_return_property(&name, getThis(), SL("_name"));
			PHALCON_THROW_EXCEPTION_FORMATW(phalcon_di_exception_ce, "Service '%s' cannot be resolved", Z_STRVAL(name));
		}
	}
}