buildJsonApiRequest($request); $document = new Document(); $data = $this->data($request, $document); event(new WillSerializeData($this, $data, $request)); $serializer = new $this->serializer($request->actor, $request->include, $request->link); $document->setData($this->serialize($serializer, $data)); return new JsonResponse($document, 200, ['content-type' => 'application/vnd.api+json']); } /** * Get the data to be serialized and assigned to the response document. * * @param JsonApiRequest $request * @param Document $document * @return array */ abstract protected function data(JsonApiRequest $request, Document $document); /** * Serialize the data as appropriate. * * @param SerializerInterface $serializer * @param array $data * @return \Tobscure\JsonApi\Elements\ElementInterface */ abstract protected function serialize(SerializerInterface $serializer, $data); /** * Extract parameters from the request input and assign them to the * request, restricted by the action's specifications. * * @param Request $request * @return JsonApiRequest */ protected function buildJsonApiRequest(Request $request) { $request = new JsonApiRequest($request->input, $request->actor, $request->http); $criteria = new Criteria($request->input); event(new BuildApiAction($this)); $request->include = $this->sanitizeInclude($criteria->getInclude()); $request->sort = $this->sanitizeSort($criteria->getSort()); $request->offset = $criteria->getOffset(); $request->limit = $this->sanitizeLimit($criteria->getLimit()); $request->link = $this->link; return $request; } /** * Sanitize an array of included relationships according to the action's * configuration. * * @param array $include * @return array */ protected function sanitizeInclude(array $include) { return array_intersect($include, array_keys($this->include)) ?: array_keys(array_filter($this->include)); } /** * Sanitize an array of sort criteria according to the action's * configuration. * * @param array $sort * @return array */ protected function sanitizeSort(array $sort) { return array_intersect_key($sort, array_flip($this->sortFields)) ?: $this->sort; } /** * Sanitize a limit according to the action's configuration. * * @param int $limit * @return int */ protected function sanitizeLimit($limit) { return min($limit, $this->limitMax) ?: $this->limit; } /** * Add pagination links to a JSON-API response, based on input parameters * and the default parameters of this action. * * @param Document $document * @param JsonApiRequest $request * @param string $url The base URL to build pagination links with. * @param integer|boolean $total The total number of results (used to build * a 'last' link), or just true if there are more results but how many * is unknown ('last' link is ommitted). * @return void */ protected function addPaginationLinks(Document $document, JsonApiRequest $request, $url, $total = true) { $input = []; if ($request->limit != $this->limit) { array_set($input, 'page.limit', $request->limit); } array_set($input, 'page.offset', 0); $document->addLink('first', $url.'?'.http_build_query($input)); if ($request->offset > 0) { array_set($input, 'page.offset', max(0, $request->offset - $request->limit)); $document->addLink('prev', $url.'?'.http_build_query($input)); } if ($total === true || $request->offset + $request->limit < $total) { array_set($input, 'page.offset', $request->offset + $request->limit); $document->addLink('next', $url.'?'.http_build_query($input)); } if ($total && $total !== true) { array_set($input, 'page.offset', $total - $request->limit); $document->addLink('last', $url.'?'.http_build_query($input)); } } }