From bb415b04861b3750940a388c43905f43e371e681 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 4 Jul 2019 15:40:45 +0930 Subject: [PATCH] wip --- composer.json | 3 +-- src/Adapter/EloquentAdapter.php | 23 ++++++++++++++++++- src/Api.php | 3 ++- src/ErrorProviderInterface.php | 2 ++ src/Exception/BadRequestException.php | 7 +++++- src/Exception/ForbiddenException.php | 9 ++++++-- .../InternalServerErrorException.php | 5 ++++ src/Exception/MethodNotAllowedException.php | 2 +- src/Handler/Concerns/SavesData.php | 6 ++--- src/Handler/Index.php | 8 +++++++ src/Schema/Attribute.php | 3 --- src/Schema/Relationship.php | 3 --- src/Serializer.php | 16 +++++++++---- 13 files changed, 69 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 716184d..43c47ea 100644 --- a/composer.json +++ b/composer.json @@ -6,8 +6,7 @@ "json-api-php/json-api": "^2.0", "psr/http-message": "^1.0", "psr/http-server-handler": "^1.0", - "spatie/macroable": "^1.0", - "zendframework/zend-diactoros": "^2.0" + "zendframework/zend-diactoros": "^2.1" }, "license": "MIT", "authors": [ diff --git a/src/Adapter/EloquentAdapter.php b/src/Adapter/EloquentAdapter.php index 43f4655..72d8ff9 100644 --- a/src/Adapter/EloquentAdapter.php +++ b/src/Adapter/EloquentAdapter.php @@ -119,7 +119,28 @@ class EloquentAdapter implements AdapterInterface public function filterByAttribute($query, Attribute $field, $value) { - $query->where($this->getAttributeProperty($field), $value); + $property = $this->getAttributeProperty($field); + + if (preg_match('/(.+)\.\.(.+)/', $value, $matches)) { + if ($matches[1] !== '*') { + $query->where($property, '>=', $matches[1]); + } + if ($matches[2] !== '*') { + $query->where($property, '<=', $matches[2]); + } + + return; + } + + foreach (['>=', '>', '<=', '<'] as $operator) { + if (strpos($value, $operator) === 0) { + $query->where($property, $operator, substr($value, strlen($operator))); + + return; + } + } + + $query->where($property, $value); } public function filterByHasOne($query, HasOne $field, array $ids) diff --git a/src/Api.php b/src/Api.php index 176b1f5..d6d9437 100644 --- a/src/Api.php +++ b/src/Api.php @@ -123,12 +123,13 @@ class Api implements RequestHandlerInterface } $errors = $e->getJsonApiErrors(); + $status = $e->getJsonApiStatus(); $data = new JsonApi\ErrorDocument( ...$errors ); - return new JsonApiResponse($data); + return new JsonApiResponse($data, $status); } public function getBaseUrl(): string diff --git a/src/ErrorProviderInterface.php b/src/ErrorProviderInterface.php index cd6687d..39fe5bb 100644 --- a/src/ErrorProviderInterface.php +++ b/src/ErrorProviderInterface.php @@ -5,4 +5,6 @@ namespace Tobscure\JsonApiServer; interface ErrorProviderInterface { public function getJsonApiErrors(): array; + + public function getJsonApiStatus(): string; } diff --git a/src/Exception/BadRequestException.php b/src/Exception/BadRequestException.php index 81b514a..5674452 100644 --- a/src/Exception/BadRequestException.php +++ b/src/Exception/BadRequestException.php @@ -34,9 +34,14 @@ class BadRequestException extends \DomainException implements ErrorProviderInter return [ new Error( new Error\Title('Bad Request'), - new Error\Status('400'), + new Error\Status($this->getJsonApiStatus()), ...$members ) ]; } + + public function getJsonApiStatus(): string + { + return '400'; + } } diff --git a/src/Exception/ForbiddenException.php b/src/Exception/ForbiddenException.php index bfa8702..852bde3 100644 --- a/src/Exception/ForbiddenException.php +++ b/src/Exception/ForbiddenException.php @@ -5,15 +5,20 @@ namespace Tobscure\JsonApiServer\Exception; use JsonApiPhp\JsonApi\Error; use Tobscure\JsonApiServer\ErrorProviderInterface; -class BadRequestException extends \DomainException implements ErrorProviderInterface +class ForbiddenException extends \DomainException implements ErrorProviderInterface { public function getJsonApiErrors(): array { return [ new Error( new Error\Title('Forbidden'), - new Error\Status('403') + new Error\Status($this->getJsonApiStatus()) ) ]; } + + public function getJsonApiStatus(): string + { + return '403'; + } } diff --git a/src/Exception/InternalServerErrorException.php b/src/Exception/InternalServerErrorException.php index 32fd795..aab5f5c 100644 --- a/src/Exception/InternalServerErrorException.php +++ b/src/Exception/InternalServerErrorException.php @@ -16,4 +16,9 @@ class InternalServerErrorException extends \RuntimeException implements ErrorPro ) ]; } + + public function getJsonApiStatus(): string + { + return '500'; + } } diff --git a/src/Exception/MethodNotAllowedException.php b/src/Exception/MethodNotAllowedException.php index 3406cfd..4173e02 100644 --- a/src/Exception/MethodNotAllowedException.php +++ b/src/Exception/MethodNotAllowedException.php @@ -5,7 +5,7 @@ namespace Tobscure\JsonApiServer\Exception; use JsonApiPhp\JsonApi\Error; use Tobscure\JsonApiServer\ErrorProviderInterface; -class BadRequestException extends \DomainException implements ErrorProviderInterface +class MethodNotAllowedException extends \DomainException implements ErrorProviderInterface { public function getJsonApiErrors(): array { diff --git a/src/Handler/Concerns/SavesData.php b/src/Handler/Concerns/SavesData.php index feb040c..60fc152 100644 --- a/src/Handler/Concerns/SavesData.php +++ b/src/Handler/Concerns/SavesData.php @@ -48,15 +48,15 @@ trait SavesData $body = (array) $body; if (! isset($body['data'])) { - throw new BadRequestException; + throw new BadRequestException('Root data attribute missing'); } if (isset($body['data']['attributes']) && ! is_array($body['data']['attributes'])) { - throw new BadRequestException; + throw new BadRequestException('data.attributes must be an object'); } if (isset($body['data']['relationships']) && ! is_array($body['data']['relationships'])) { - throw new BadRequestException; + throw new BadRequestException('data.relationships must be an object'); } return array_merge( diff --git a/src/Handler/Index.php b/src/Handler/Index.php index e2b2eea..ca2dd98 100644 --- a/src/Handler/Index.php +++ b/src/Handler/Index.php @@ -127,6 +127,14 @@ class Index implements RequestHandlerInterface unset($queryParams['page']['offset']); } + if (isset($queryParams['filter'])) { + foreach ($queryParams['filter'] as $k => &$v) { + if ($v === null) { + $v = ''; + } + } + } + $queryString = http_build_query($queryParams); return $selfUrl.($queryString ? '?'.$queryString : ''); diff --git a/src/Schema/Attribute.php b/src/Schema/Attribute.php index 2ce76f2..3708754 100644 --- a/src/Schema/Attribute.php +++ b/src/Schema/Attribute.php @@ -3,12 +3,9 @@ namespace Tobscure\JsonApiServer\Schema; use Closure; -use Spatie\Macroable\Macroable; class Attribute extends Field { - use Macroable; - public $location = 'attributes'; public $sortable = false; public $sorter; diff --git a/src/Schema/Relationship.php b/src/Schema/Relationship.php index e842865..a128c4b 100644 --- a/src/Schema/Relationship.php +++ b/src/Schema/Relationship.php @@ -3,13 +3,10 @@ namespace Tobscure\JsonApiServer\Schema; use Closure; -use Spatie\Macroable\Macroable; use Tobscure\JsonApiServer\Handler\Show; abstract class Relationship extends Field { - use Macroable; - public $location = 'relationships'; public $linkage; public $hasLinks = true; diff --git a/src/Serializer.php b/src/Serializer.php index 2177460..78ed6dc 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -34,7 +34,7 @@ class Serializer $schema = $resource->getSchema(); $data = [ - 'type' => $resource->getType(), + 'type' => $type = $resource->getType(), 'id' => $adapter->getId($model), 'fields' => [], 'links' => [], @@ -43,9 +43,17 @@ class Serializer $resourceUrl = $this->api->getBaseUrl().'/'.$data['type'].'/'.$data['id']; - ksort($schema->fields); + $fields = $schema->fields; - foreach ($schema->fields as $name => $field) { + $queryParams = $this->request->getQueryParams(); + + if (isset($queryParams['fields'][$type])) { + $fields = array_intersect_key($fields, array_flip(explode(',', $queryParams['fields'][$type]))); + } + + ksort($fields); + + foreach ($fields as $name => $field) { if (! ($field->isVisible)($this->request, $model)) { continue; } @@ -132,7 +140,7 @@ class Serializer if ($field->getter) { $value = ($field->getter)($this->request, $model); } else { - $value = $isLinkage ? $adapter->getHasMany($model, $field) : null; + $value = ($isLinkage || $isIncluded) ? $adapter->getHasMany($model, $field) : null; } $identifiers = [];