getUriFromRequest(); $request = $this->getPsrRequest(); switch ($request->getMethod()) { case 'GET': $response = $this->get($uri); break; case 'PUT': $response = $this->put($uri); break; case 'POST': $response = $this->post(); break; case 'DELETE': $response = $this->delete($uri); break; default: throw new common_exception_BadRequest($request->getUri()->getPath()); } $this->returnSuccess($response); } catch (Exception $e) { if ( $e instanceof \common_exception_ValidationFailed && $alias = $this->reverseSearchAlias($e->getField()) ) { $e = new \common_exception_ValidationFailed($alias, null, $e->getCode()); } $this->returnFailure($e); } } /** * Return crud service * * @throws common_Exception * * @return tao_models_classes_CrudService */ protected function getCrudService() { if (!$this->service) { throw new common_Exception('Crud service is not set.'); } return $this->service; } /** * Method to wrap fetching to service: * - get() if uri is not null * - getAll() if uri is null * * @param string|null $uri * * @throws common_Exception * @throws common_Exception_NoContent * @throws common_exception_InvalidArgumentType * @throws common_exception_PreConditionFailure * * @return object|stdClass */ protected function get($uri = null) { if ($uri !== null) { if ($this->getCrudService()->isInScope($uri) === false) { throw new common_exception_PreConditionFailure( 'The URI must be a valid resource under the root Class' ); } return $this->getCrudService()->get($uri); } else { return $this->getCrudService()->getAll(); } } /** * Method to wrap deleting to service if uri is not null * * @param string|null $uri * * @throws common_Exception * @throws common_exception_BadRequest * @throws common_exception_InvalidArgumentType * @throws common_exception_NoContent * @throws common_exception_PreConditionFailure */ protected function delete($uri = null) { if ($uri === null) { throw new common_exception_BadRequest('Delete method requires an uri parameter'); } elseif ($this->getCrudService()->isInScope($uri) === false) { throw new common_exception_PreConditionFailure( 'The URI must be a valid resource under the root Class' ); } return $this->getCrudService()->delete($uri); } /** * Method to wrap creating to service * * @OA\Schema( * schema="tao.CommonRestModule.CreatedResource", * description="Created resource data", * @OA\Property( * property="uriResource", * type="string", * example="http://sample/first.rdf#i1536680377163171" * ), * @OA\Property( * property="label", * type="string" * ), * @OA\Property( * property="comment", * type="string" * ) * ) * @OA\Schema( * schema="tao.CommonRestModule.CreatedResourceResponse", * description="Created resource data", * allOf={ * @OA\Schema(ref="#/components/schemas/tao.RestTrait.BaseResponse") * }, * @OA\Property( * property="data", * ref="#/components/schemas/tao.CommonRestModule.CreatedResource" * ) * ) * * @throws common_Exception * @throws common_exception_RestApi * * @return mixed */ protected function post() { try { return $this->getCrudService()->createFromArray($this->getParameters()); } catch (common_exception_PreConditionFailure $e) { throw new common_exception_RestApi($e->getMessage()); } } /** * Method to wrap to updating to service if uri is not null * * @param string|null $uri * * @throws common_Exception * @throws common_exception_BadRequest * @throws common_exception_InvalidArgumentType * @throws common_exception_NoContent * @throws common_exception_PreConditionFailure * @throws common_exception_RestApi * * @return mixed */ protected function put($uri) { if ($uri === null) { throw new common_exception_BadRequest('Update method requires an uri parameter'); } elseif ($this->getCrudService()->isInScope($uri) === false) { throw new common_exception_PreConditionFailure( 'The URI must be a valid resource under the root Class' ); } try { return $this->getCrudService()->update($uri, $this->getParameters()); } catch (common_exception_PreConditionFailure $e) { throw new common_exception_RestApi($e->getMessage()); } } private function getPostData(): array { if (!is_array($parameters = $this->getPsrRequest()->getParsedBody())) { $parameters = []; } return $parameters; } private function getBodyData(): array { $data = $this->getPsrRequest()->getBody()->getContents(); if ($data && $this->hasHeader('Accept') && current($this->getHeader('Accept')) === 'application/json') { $data = @json_decode($data, true); } return is_array($data) ? $data : []; } private function getRequestData(): array { return array_merge($this->getPostData(), $this->getBodyData()); } /** * Returns all parameters that are URIs or Aliased with values * * @throws \common_exception_RestApi If a mandatory parameter is not found * * @return array */ protected function getParameters() { $effectiveParameters = []; $missedAliases = []; $parameters = $this->getRequestData(); foreach ($this->getParametersAliases() as $checkParameterShort => $checkParameterUri) { if (array_key_exists($checkParameterUri, $parameters)) { $effectiveParameters[$checkParameterUri] = $parameters[$checkParameterUri]; } elseif (array_key_exists($checkParameterShort, $parameters)) { $effectiveParameters[$checkParameterUri] = $parameters[$checkParameterShort]; } elseif ($this->isRequiredParameter($checkParameterShort)) { $missedAliases[] = $checkParameterShort; } } if (!empty($missedAliases)) { throw new \common_exception_RestApi( 'Missed required parameters: ' . implode(', ', $missedAliases) ); } return $effectiveParameters; } /** * Return required parameters by method * Should return an array with key as HTTP method and value as array of parameters * * @return array */ protected function getParametersRequirements() { return [ 'put' => ['uri'], 'delete' => ['uri'], ]; } /** * Default parameters aliases, * Map from get parameter name to class uri * * @return array */ protected function getParametersAliases() { return [ 'label' => OntologyRdfs::RDFS_LABEL, 'comment' => OntologyRdfs::RDFS_COMMENT, 'type' => OntologyRdf::RDF_TYPE, ]; } /** * @param string $paramName * * @return false|int|string */ protected function reverseSearchAlias($paramName) { return array_search($paramName, $this->getParametersAliases(), true); } /** * Defines if the parameter is mandatory according: * - getParametersRequirements array * - HTTP method * * @param string $parameter The alias name or uri of a parameter * * @return bool */ protected function isRequiredParameter($parameter) { $requirements = array_change_key_case($this->getParametersRequirements(), CASE_LOWER); $method = strtolower($this->getPsrRequest()->getMethod()); if (!isset($requirements[$method])) { return false; } elseif (in_array($parameter, $requirements[$method], true)) { return true; } $isRequired = false; // The requirements may have been declared using URIs, look up for the URI $aliases = $this->getParametersAliases(); if (isset($aliases[$parameter])) { $isRequired = in_array($aliases[$parameter], $requirements[$method], true); } return $isRequired; } /** * @throws common_exception_InvalidArgumentType * * @return string|null */ protected function getUriFromRequest() { $uri = null; $request = $this->getPsrRequest(); $parsedBody = $request->getParsedBody(); $queryParams = $request->getQueryParams(); if (is_array($parsedBody) && array_key_exists('uri', $parsedBody)) { $uri = $parsedBody['uri']; } elseif (array_key_exists('uri', $queryParams)) { $uri = $queryParams['uri']; } if ($uri !== null && common_Utils::isUri($uri) === false) { throw new common_exception_InvalidArgumentType(); } return $uri; } }