/** * Parse the result given by the JSON RPC Server * * @param Collection\Request $request * @param mixed $result * @param mixed $info * @return Collection\Response */ protected function parseResponse(Collection\Request $request, $result, $info) { // Rewind to collection to start from the beginning $request->rewind(); if (empty($result) && $request->isBatch() === false && $request->current()->getId() !== null) { throw new Exception\InvalidResponse('Client parse error', static::CLIENT_PARSE_ERROR); } // First go through the layer stack $result = $this->protocolLayerStack->handleResponse($result); $json = json_decode($result, true); if (is_array($json) === false) { throw new Exception\InvalidResponse('Client parse error', static::CLIENT_PARSE_ERROR); } // Check varaibles $hasIdKey = array_key_exists('id', $json); $isBatch = $request->isBatch(); // Check if we have a batch result if ($isBatch === true && $hasIdKey === true) { throw new Exception\InvalidResponse('Client expected batch result', static::CLIENT_EXPECTED_BATCH); // check if we have single result } else { if ($isBatch === false && $hasIdKey === false) { throw new Exception\InvalidResponse('Client expected single result', static::CLIENT_EXPECTED_SINGLE); } } // No batch, so we make it one if ($isBatch === false) { $json = array($json); } // Create collection response $responses = new Collection\Response(); // Loop through all the responses foreach ($json as $rawResponse) { $response = new Entity\Response(); // Fetch the items from the response array $id = $this->getArrayItem('id', $rawResponse); $jsonrpc = $this->getArrayItem('jsonrpc', $rawResponse); $result = $this->getArrayItem('result', $rawResponse, null); $error = $this->getArrayItem('error', $rawResponse, null); // Set general data $response->setId($id)->setJsonrpc($jsonrpc); // Determine which item to set if ($error === null) { $response->setResult($result); } else { // hydrate error information $errorObject = new Entity\Error(); $errorObject->setCode($this->getArrayItem('code', $error)); $errorObject->setData($this->getArrayItem('data', $error)); $errorObject->setMessage($this->getArrayItem('message', $error)); $response->setError($errorObject); } // When callback has been registered use this if ($request->hasIdCallback($response->getId())) { $request->performCallback($response); } // append the response to the collection $responses->append($response); } // return the collection return $responses; }
/** * Parse the incoming request * * @param Entity\Request $request * @return Entity\Response */ protected function parseRequest(Entity\Request $request) { // Check if the method has been set if ($request->getMethod() === null) { throw new Exception\InvalidRequest('Invalid request', static::INVALID_REQUEST); } // normalize the name $methodName = strtolower($request->getMethod()); $namespace = 'global'; if (strpos($methodName, '.') !== false) { list($namespace, $methodName) = explode('.', $methodName, 2); } // Check if the namespace has been registered if ($this->handlers->offsetExists($namespace) === false) { throw new Exception\InvalidRequest('Method not found', static::METHOD_NOT_FOUND); } $methods = $this->getHandlerReflectionMaker()->reflect($this->handlers->offsetGet($namespace)); // Check if the method exists if ($methods->offsetExists($methodName) === false) { throw new Exception\InvalidRequest('Method not found', static::METHOD_NOT_FOUND); } // Runtime variables $numericArray = true; $firstIteration = true; // Loop through the request params for the type of arguments foreach ($request->getParams() as $offset => $param) { $isNumeric = (int) $offset === $offset; // Associative and numeric cannot be used together if ($firstIteration === false && $isNumeric !== $numericArray) { throw new Exception\InvalidRequest('Invalid params', static::INVALID_PARAMS); } // Set the isNumeric flag $numericArray = $isNumeric; // We are not iterating the first anymore $firstIteration = false; } // List of arguments for the callable $arguments = array(); // Get method information $method = $methods->offsetGet($methodName); $handler = $this->getHandler($namespace); // Loop through method information foreach ($method->getParameters() as $parameter) { // decide which offset to use if ($numericArray === true) { $offset = $parameter->getIndex(); } else { $offset = $parameter->getName(); } // check if the offset exists $offsetExists = $request->getParams()->offsetExists($offset); // Check if the argument is required if ($parameter->getRequired() && $offsetExists === false) { throw new Exception\InvalidRequest('Invalid params', static::INVALID_PARAMS); } // Add value to the argument list $arguments[] = $offsetExists ? $request->getParams()->offsetGet($offset) : $parameter->getDefault(); } // Perform action on the handle object $result = call_user_func_array(array($handler, $method->getName()), $arguments); // NULL means no response output if ($request->getId() === null) { return null; } // Create response object $response = new Entity\Response(); $response->setId($request->getId()); $response->setJsonrpc($request->getJsonrpc()); $response->setResult($result); // Return the response return $response; }