phalconplus Documentation v1.3.0-development
Class
Class PhalconPlus Rpc Client Adapter

# Local

        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);
        }
    }