namespace PhalconPlus\Rpc\Client\Adapter;
use PhalconPlus\Rpc\Client\AbstractClient;
use PhalconPlus\Base\ProtoBuffer;
use PhalconPlus\Base\Exception as BaseException;
class Local extends AbstractClient
{
private config;
private di;
public function __construct(<\Phalcon\DI> di)
{
let this->di = di;
let this->config = di->get("config");
}
private function callByParams(string! service, string! method, request)
{
var serviceObj = null,
methodReflection = null,
serviceClass = "";
let serviceClass = service->upperfirst() . "Service";
if !class_exists(serviceClass) {
throw new BaseException("Service class not exists: " . serviceClass);
}
let serviceObj = new {serviceClass}(this->di);
var e;
try {
let methodReflection = new \ReflectionMethod(serviceObj, method);
} catch \ReflectionException, e {
throw new BaseException("Service:method not found. Detail: " . serviceClass . " : " . method . ". RawException: ". e->getMessage());
}
error_log("ServerClass: " . serviceClass);
error_log("InvokeMethod: " . method);
if request == null && methodReflection->getNumberOfRequiredParameters() > 0 {
throw new BaseException(service."::".method." need required params");
}
if methodReflection->getNumberOfParameters() > 0 {
error_log("InputParam: " . var_export(request, true));
// If get an object, must be instance of or it's subclasses
if is_object(request) && (request instanceof ProtoBuffer) {
error_log("Request is object and instanceof ProtoBuffer: ". get_class(request));
} elseif is_array(request) {
var tmp = request,
param = null,
paramClass = "";
let param = new \ReflectionParameter([serviceClass, method], 0);
if param->getClass() {
let paramClass = param->getClass()->getName();
let request = new {paramClass}();
request->softClone(tmp);
} else {
throw new BaseException("Service class:method definition is invalid. Detail: " . service . " : " . method . ". Request: " . json_encode(request));
}
} elseif null == request {
// nothing here...
} else {
throw new BaseException("No service found: " . serviceClass . "::" . method);
}
}
error_log("Finally Requst: ". var_export(request, true));
var response;
// Invoke target method
try {
// We expected type
let response = methodReflection->invokeArgs(serviceObj, [request]);
} catch \Exception, e {
throw new BaseException(e->getMessage());
}
// We do not allow to return #Resource type. And if an object returned, we expected type
if is_object(response) && !(response instanceof ProtoBuffer) {
throw new BaseException("Your output is not allowed. Response: " . get_class(response) . ". We expect scalar type or ");
} elseif is_resource(response) {
throw new BaseException("Your output is not allowed. Response: #Resource.");
}
return response;
}
public function callByObject(array rawData)
{
var service, method, request;
error_log("Local callByObject: " . var_export(rawData, true));
if !fetch service, rawData["service"] {
throw new BaseException("service " . service . " not exists");
}
if !fetch method, rawData["method"] {
throw new BaseException("method " . method . " not exists");
}
if !fetch request, rawData["args"] {
let request = null;
}
let service = this->namePrefix . trim(service);
let method = trim(method);
if empty service || empty method {
throw new BaseException("service:method(args) must exists. All of them!!!");
}
error_log("Invoke callByParams with (" . service . ", " . method . ")");
return this->callByParams(service, method, request);
}
}