Skip to content

Commit

Permalink
wip: refactor formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
jiannei committed Oct 11, 2023
1 parent 88b7993 commit b9af97a
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 193 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
],
"require": {
"php": "^8.0",
"ext-json": "*"
"ext-json": "*",
"spatie/laravel-fractal": "^6.0"
},
"require-dev": {
"orchestra/testbench": "^8.0",
Expand Down
12 changes: 4 additions & 8 deletions src/Contracts/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface Format
* @param null $errors
* @return array
*/
public function data(?array $data, ?string $message, int $code, $errors = null): array;
public function format(?array $data, ?string $message, int $code, $errors = null): array;

/**
* Format paginator data.
Expand All @@ -39,7 +39,7 @@ public function data(?array $data, ?string $message, int $code, $errors = null):
* @param int $option
* @return array
*/
public function paginator(AbstractPaginator|AbstractCursorPaginator $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array;
public function paginator(AbstractPaginator|AbstractCursorPaginator $resource);

/**
* Format collection resource data.
Expand All @@ -51,17 +51,13 @@ public function paginator(AbstractPaginator|AbstractCursorPaginator $resource, s
* @param int $option
* @return array
*/
public function resourceCollection(ResourceCollection $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array;
public function resourceCollection(ResourceCollection $resource);

/**
* Format JsonResource Data.
*
* @param JsonResource $resource
* @param string $message
* @param int $code
* @param array $headers
* @param int $option
* @return array
*/
public function jsonResource(JsonResource $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array;
public function jsonResource(JsonResource $resource);
}
140 changes: 79 additions & 61 deletions src/Support/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,22 @@

namespace Jiannei\Response\Laravel\Support;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Traits\Macroable;
use League\Fractal\Pagination\Cursor;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Serializer\ArraySerializer;
use League\Fractal\Serializer\DataArraySerializer;
use Spatie\Fractal\Fractal;

class Format implements \Jiannei\Response\Laravel\Contracts\Format
{
Expand Down Expand Up @@ -47,7 +55,7 @@ public function response($data = [], int $status = 200, array $headers = [], int
* @param null $errors
* @return array
*/
public function data(?array $data, ?string $message, int $code, $errors = null): array
public function format(?array $data, ?string $message, int $code, $errors = null): array
{
return $this->formatDataFields([
'status' => $this->formatStatus($code),
Expand All @@ -62,61 +70,100 @@ public function data(?array $data, ?string $message, int $code, $errors = null):
* Format paginator data.
*
* @param AbstractPaginator|AbstractCursorPaginator $resource
* @param string $message
* @param int $code
* @param array $headers
* @param int $option
* @return array
*/
public function paginator(AbstractPaginator|AbstractCursorPaginator $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array
public function paginator(AbstractPaginator|AbstractCursorPaginator $resource)
{
$paginated = $resource->toArray();
$fractal = fractal()->collection($resource, function ($item) {
return $item->toArray();
})->serializeWith(DataArraySerializer::class);

return tap($fractal, function (Fractal $item) use ($resource) {
if ($resource instanceof CursorPaginator) {
return $item->withCursor(new Cursor(
$resource->cursor()?->encode(),
$resource->previousCursor()?->encode(),
$resource->nextCursor()?->encode(),
count($resource->items()))
);
}

$paginationInformation = $this->formatPaginatedData($paginated);
if ($resource instanceof LengthAwarePaginator) {
return $item->paginateWith(new IlluminatePaginatorAdapter($resource));
}

$data = array_merge_recursive(['data' => $paginated['data']], $paginationInformation);
if ($resource instanceof Paginator) {
return $item->addMeta([
'pagination' => [
'count' => count($resource->items()),
'per_page' => $resource->perPage(),
'current_page' => $resource->currentPage(),
'links' => [
'previous' => $resource->previousPageUrl(),
'next' => $resource->nextPageUrl()
]
],
]);
}

return $this->data($data, $message, $code);
return $item;
});
}

/**
* Format collection resource data.
*
* @param ResourceCollection $resource
* @param string $message
* @param int $code
* @param array $headers
* @param int $option
* @param ResourceCollection $collection
* @return array
*/
public function resourceCollection(ResourceCollection $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array
public function resourceCollection(ResourceCollection $collection): array
{
$data = array_merge_recursive(['data' => $resource->resolve(request())], $resource->with(request()), $resource->additional);
if ($resource->resource instanceof AbstractPaginator || $resource->resource instanceof AbstractCursorPaginator) {
$paginated = $resource->resource->toArray();
$paginationInformation = $this->formatPaginatedData($paginated);
$fractal = fractal()->collection($collection->resource,function (JsonResource $resource){
return array_merge_recursive($resource->resolve(request()), $resource->with(request()), $resource->additional);
})->serializeWith(DataArraySerializer::class);

return tap($fractal, function (Fractal $item) use ($collection) {
if ($collection->resource instanceof CursorPaginator) {
return $item->withCursor(new Cursor(
$collection->resource->cursor()?->encode(),
$collection->resource->previousCursor()?->encode(),
$collection->resource->nextCursor()?->encode(),
count($collection->resource->items()))
);
}

$data = array_merge_recursive($data, $paginationInformation);
}
if ($collection->resource instanceof LengthAwarePaginator) {
return $item->paginateWith(new IlluminatePaginatorAdapter($collection->resource));
}

if ($collection->resource instanceof Paginator) {
return $item->addMeta([
'pagination' => [
'count' => count($collection->resource->items()),
'per_page' => $collection->resource->perPage(),
'current_page' => $collection->resource->currentPage(),
'links' => [
'previous' => $collection->resource->previousPageUrl(),
'next' => $collection->resource->nextPageUrl()
]
],
]);
}

return $this->data($data, $message, $code);
return $item;
});
}

/**
* Format JsonResource Data.
*
* @param JsonResource $resource
* @param string $message
* @param int $code
* @param array $headers
* @param int $option
* @return array
*/
public function jsonResource(JsonResource $resource, string $message = '', int $code = 200, array $headers = [], int $option = 0): array
public function jsonResource(JsonResource $resource)
{
$resourceData = array_merge_recursive($resource->resolve(request()), $resource->with(request()), $resource->additional);

return $this->data($resourceData, $message, $code);
return fractal()->item($resource->resource,function (JsonResource $resource){
return array_merge_recursive($resource->resolve(request()), $resource->with(request()), $resource->additional);
})->serializeWith(ArraySerializer::class);
}

/**
Expand Down Expand Up @@ -166,35 +213,6 @@ protected function formatStatusCode($code): int
return (int) substr($code, 0, 3);
}

/**
* Format paginated data.
*
* @param array $paginated
* @return array
*/
protected function formatPaginatedData(array $paginated): array
{
return [
'meta' => [
'pagination' => [
'total' => $paginated['total'] ?? 0,
'count' => $paginated['to'] ?? 0,
'per_page' => $paginated['per_page'] ?? 0,
'current_page' => $paginated['current_page'] ?? 0,
'total_pages' => $paginated['last_page'] ?? 0,
'links' => [
'previous' => $paginated['prev_page_url'] ?? '',
'next' => $paginated['next_page_url'] ?? '',
],
'cursor' => [
'previous' => $paginated['prev_cursor'] ?? '',
'next' => $paginated['next_cursor'] ?? '',
],
],
],
];
}

/**
* Format response data fields.
*
Expand Down
73 changes: 0 additions & 73 deletions src/Support/Serializers/ArraySerializer.php

This file was deleted.

27 changes: 0 additions & 27 deletions src/Support/Serializers/SimpleArraySerializer.php

This file was deleted.

28 changes: 5 additions & 23 deletions src/Support/Traits/JsonResponseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,39 +199,21 @@ public function fail(string $message = '', int $code = 500, $errors = null, arra
public function success($data = [], string $message = '', int $code = 200, array $headers = [], int $option = 0)
{
if ($data instanceof ResourceCollection) {
return tap(
$this->formatter->response($this->formatter->resourceCollection(...func_get_args()), $code, $headers, $option),
function ($response) use ($data) {
$response->original = $data->resource->map(
function ($item) {
return is_array($item) ? Arr::get($item, 'resource') : $item->resource;
}
);

$data->withResponse(request(), $response);
}
);
$data = $this->formatter->resourceCollection($data);
}

if ($data instanceof JsonResource) {
return tap(
$this->formatter->response($this->formatter->jsonResource(...func_get_args()), $code, $headers, $option),
function ($response) use ($data) {
$response->original = $data->resource;

$data->withResponse(request(), $response);
}
);
$data = $this->formatter->jsonResource($data);
}

if ($data instanceof AbstractPaginator || $data instanceof AbstractCursorPaginator) {
return $this->formatter->response($this->formatter->paginator(...func_get_args()), $code, $headers, $option);
$data = $this->formatter->paginator($data);
}

if ($data instanceof Arrayable || (is_object($data) && method_exists($data, 'toJson'))) {
if ($data instanceof Arrayable || (is_object($data) && method_exists($data, 'toArray'))) {
$data = $data->toArray();
}

return $this->formatter->response($this->formatter->data(Arr::wrap($data), $message, $code), $code, $headers, $option);
return $this->formatter->response($this->formatter->format(Arr::wrap($data), $message, $code), $code, $headers, $option);
}
}

0 comments on commit b9af97a

Please sign in to comment.