From 73ec0b17f60da2c8c6ce215ff6356f9685355cfe Mon Sep 17 00:00:00 2001 From: Clemens John <clemens.john@floh1111.de> Date: Mon, 23 Jan 2017 10:42:36 +0100 Subject: [PATCH] Fix namespaces and paths. Add Exceptions and resources Signed-off-by: Clemens John <clemens.john@floh1111.de> --- composer.json | 3 +- resources/schemas/schema | 380 ++++++++++++++++++ resources/schemas/schema-create | 28 ++ .../Exceptions/BodyValidationException.php | 25 ++ .../CollectionResourceController.php | 4 +- .../Controllers/DefaultResourceController.php | 6 +- .../DocumentResourceController.php | 4 +- src/Http/Controllers/JsonApiController.php | 2 +- .../OneToOneResourceController.php | 4 +- src/Serializers/BasicSerializer.php | 2 +- src/Traits/CollectionResourceTrait.php | 2 +- src/Traits/DocumentResourceTrait.php | 2 +- src/Traits/StoreResourceTrait.php | 8 +- 13 files changed, 452 insertions(+), 18 deletions(-) create mode 100644 resources/schemas/schema create mode 100644 resources/schemas/schema-create create mode 100644 src/Exceptions/Exceptions/BodyValidationException.php diff --git a/composer.json b/composer.json index 370dd0e..2225274 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "Netmon\\JsonApi\\": "src/", "Netmon\\JsonApi\\Http\\Controllers\\": "src/Http/Controllers/", "Netmon\\JsonApi\\Serializers\\": "src/Serializers/", - "Netmon\\JsonApi\\Traits\\": "src/Traits/" + "Netmon\\JsonApi\\Traits\\": "src/Traits/", + "Netmon\\JsonApi\\Exceptions\\Exceptions": "src/Exceptions/Exceptions/" } }, "require": { diff --git a/resources/schemas/schema b/resources/schemas/schema new file mode 100644 index 0000000..7fe78cd --- /dev/null +++ b/resources/schemas/schema @@ -0,0 +1,380 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "JSON API Schema", + "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org", + "oneOf": [ + { + "$ref": "file://schema#/definitions/success" + }, + { + "$ref": "file://schema#/definitions/failure" + }, + { + "$ref": "file://schema#/definitions/info" + } + ], + + "definitions": { + "success": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "file://schema#/definitions/data" + }, + "included": { + "description": "To reduce the number of HTTP requests, servers **MAY** allow responses that include related resources along with the requested primary resources. Such responses are called \"compound documents\".", + "type": "array", + "items": { + "$ref": "file://schema#/definitions/resource" + }, + "uniqueItems": true + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + }, + "links": { + "description": "Link members related to the primary data.", + "allOf": [ + { + "$ref": "file://schema#/definitions/links" + }, + { + "$ref": "file://schema#/definitions/pagination" + } + ] + }, + "jsonapi": { + "$ref": "file://schema#/definitions/jsonapi" + } + }, + "additionalProperties": false + }, + "failure": { + "type": "object", + "required": [ + "errors" + ], + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "file://schema#/definitions/error" + }, + "uniqueItems": true + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + }, + "jsonapi": { + "$ref": "file://schema#/definitions/jsonapi" + } + }, + "additionalProperties": false + }, + "info": { + "type": "object", + "required": [ + "meta" + ], + "properties": { + "meta": { + "$ref": "file://schema#/definitions/meta" + }, + "links": { + "$ref": "file://schema#/definitions/links" + }, + "jsonapi": { + "$ref": "file://schema#/definitions/jsonapi" + } + }, + "additionalProperties": false + }, + + "meta": { + "description": "Non-standard meta-information that can not be represented as an attribute or relationship.", + "type": "object", + "additionalProperties": true + }, + "data": { + "description": "The document's \"primary data\" is a representation of the resource or collection of resources targeted by a request.", + "oneOf": [ + { + "$ref": "file://schema#/definitions/resource" + }, + { + "description": "An array of resource objects, an array of resource identifier objects, or an empty array ([]), for requests that target resource collections.", + "type": "array", + "items": { + "$ref": "file://schema#/definitions/resource" + }, + "uniqueItems": true + } + ] + }, + + "newResource": { + "description": "\"Resource objects\" appear in a JSON API document to represent resources.", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string" + }, + "id": { + "description": "A server **MAY** accept a client-generated ID along with a request to create a resource. An ID **MUST** be specified with an id key, the value of which **MUST** be a universally unique identifier. The client **SHOULD** use a properly generated and formatted UUID as described in RFC 4122.", + "type": "string" + }, + "attributes": { + "$ref": "file://schema#/definitions/attributes" + }, + "relationships": { + "$ref": "file://schema#/definitions/relationships" + }, + "links": { + "$ref": "file://schema#/definitions/links" + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + } + }, + "additionalProperties": false + }, + "resource": { + "description": "\"Resource objects\" appear in a JSON API document to represent resources.", + "allOf": [ + { + "$ref": "file://schema#/definitions/newResource" + }, + { + "required": [ + "type", + "id" + ] + } + ] + }, + + "links": { + "description": "A resource object **MAY** contain references to other resource objects (\"relationships\"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.", + "type": "object", + "properties": { + "self": { + "description": "A `self` member, whose value is a URL for the relationship itself (a \"relationship URL\"). This URL allows the client to directly manipulate the relationship. For example, it would allow a client to remove an `author` from an `article` without deleting the people resource itself.", + "type": "string", + "format": "uri" + }, + "related": { + "$ref": "file://schema#/definitions/link" + } + }, + "additionalProperties": true + }, + "link": { + "description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.", + "oneOf": [ + { + "description": "A string containing the link's URL.", + "type": "string", + "format": "uri" + }, + { + "type": "object", + "required": [ + "href" + ], + "properties": { + "href": { + "description": "A string containing the link's URL.", + "type": "string", + "format": "uri" + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + } + } + } + ] + }, + + "attributes": { + "description": "Members of the attributes object (\"attributes\") represent information about the resource object in which it's defined.", + "type": "object", + "patternProperties": { + "^(?!relationships$|links$)\\w[-\\w_]*$": { + "description": "Attributes may contain any valid JSON value." + } + }, + "additionalProperties": false + }, + + "relationships": { + "description": "Members of the relationships object (\"relationships\") represent references from the resource object in which it's defined to other resource objects.", + "type": "object", + "patternProperties": { + "^\\w[-\\w_]*$": { + "properties": { + "links": { + "$ref": "file://schema#/definitions/links" + }, + "data": { + "description": "Member, whose value represents \"resource linkage\".", + "oneOf": [ + { + "$ref": "file://schema#/definitions/relationshipToOne" + }, + { + "$ref": "file://schema#/definitions/relationshipToMany" + } + ] + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "relationshipToOne": { + "description": "References to other resource objects in a to-one (\"relationship\"). Relationships can be specified by including a member in a resource's links object.", + "anyOf": [ + { + "$ref": "file://schema#/definitions/empty" + }, + { + "$ref": "file://schema#/definitions/linkage" + } + ] + }, + "relationshipToMany": { + "description": "An array of objects each containing \"type\" and \"id\" members for to-many relationships.", + "type": "array", + "items": { + "$ref": "file://schema#/definitions/linkage" + }, + "uniqueItems": true + }, + "empty": { + "description": "Describes an empty to-one relationship.", + "type": ["object", "null"], + "properties": {}, + "additionalProperties": false + }, + "linkage": { + "description": "The \"type\" and \"id\" to non-empty members.", + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "additionalProperties": false + }, + "pagination": { + "type": "object", + "properties": { + "first": { + "description": "The first page of data", + "oneOf": [ + { "type": "string", "format": "uri" }, + { "type": "null" } + ] + }, + "last": { + "description": "The last page of data", + "oneOf": [ + { "type": "string", "format": "uri" }, + { "type": "null" } + ] + }, + "prev": { + "description": "The previous page of data", + "oneOf": [ + { "type": "string", "format": "uri" }, + { "type": "null" } + ] + }, + "next": { + "description": "The next page of data", + "oneOf": [ + { "type": "string", "format": "uri" }, + { "type": "null" } + ] + } + } + }, + + "jsonapi": { + "description": "An object describing the server's implementation", + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + } + }, + "additionalProperties": false + }, + + "error": { + "type": "object", + "properties": { + "id": { + "description": "A unique identifier for this particular occurrence of the problem.", + "type": "string" + }, + "links": { + "$ref": "file://schema#/definitions/links" + }, + "status": { + "description": "The HTTP status code applicable to this problem, expressed as a string value.", + "type": "string" + }, + "code": { + "description": "An application-specific error code, expressed as a string value.", + "type": "string" + }, + "title": { + "description": "A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.", + "type": "string" + }, + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" + }, + "source": { + "type": "object", + "properties": { + "pointer": { + "description": "A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. \"/data\" for a primary data object, or \"/data/attributes/title\" for a specific attribute].", + "type": "string" + }, + "parameter": { + "description": "A string indicating which query parameter caused the error.", + "type": "string" + } + } + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + } + }, + "additionalProperties": false + } + } +} diff --git a/resources/schemas/schema-create b/resources/schemas/schema-create new file mode 100644 index 0000000..e2abd78 --- /dev/null +++ b/resources/schemas/schema-create @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "JSON API Schema", + "description": "This is a schema for clients creating resources in the JSON API format. For more, see http://jsonapi.org", + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "file://schema-create#/definitions/newData" + }, + "meta": { + "$ref": "file://schema#/definitions/meta" + }, + "jsonapi": { + "$ref": "file://schema#/definitions/jsonapi" + } + }, + "additionalProperties": false, + + "definitions": { + "newData": { + "description": "A resource can be created by sending a `POST` request to a URL that represents a collection of resources. The request **MUST** include a single resource object as primary data.", + "$ref": "file://schema#/definitions/newResource" + } + } +} diff --git a/src/Exceptions/Exceptions/BodyValidationException.php b/src/Exceptions/Exceptions/BodyValidationException.php new file mode 100644 index 0000000..52ced6f --- /dev/null +++ b/src/Exceptions/Exceptions/BodyValidationException.php @@ -0,0 +1,25 @@ +<?php + +namespace Netmon\JsonApi\Exceptions\Exceptions; + +use Exception; +use Illuminate\Support\MessageBag; + +class BodyValidationException extends Exception +{ + protected $code = 400; + protected $validationErrors; + + public function __construct ( + $message = "Request body validation failed.", + MessageBag $validationErrors, + Exception $previous = NULL + ) { + parent::__construct($message, $this->code, $previous); + $this->validationErrors = $validationErrors; + } + + public function getValidationErrors() { + return $this->validationErrors; + } +} diff --git a/src/Http/Controllers/CollectionResourceController.php b/src/Http/Controllers/CollectionResourceController.php index e27da6b..1dc153b 100644 --- a/src/Http/Controllers/CollectionResourceController.php +++ b/src/Http/Controllers/CollectionResourceController.php @@ -1,8 +1,8 @@ <?php -namespace Netmon\Server\App\Http\Controllers\JsonApi; +namespace Netmon\JsonApi\Http\Controllers\JsonApi; -use Netmon\Server\App\Traits\CollectionResourceTrait; +use Netmon\JsonApi\Traits\CollectionResourceTrait; abstract class CollectionResourceController extends JsonApiController { diff --git a/src/Http/Controllers/DefaultResourceController.php b/src/Http/Controllers/DefaultResourceController.php index 06f1045..a489958 100644 --- a/src/Http/Controllers/DefaultResourceController.php +++ b/src/Http/Controllers/DefaultResourceController.php @@ -1,9 +1,9 @@ <?php -namespace Netmon\Server\App\Http\Controllers\JsonApi; +namespace Netmon\JsonApi\Http\Controllers\JsonApi; -use Netmon\Server\App\Traits\StoreResourceTrait; -use Netmon\Server\App\Traits\CollectionResourceTrait; +use Netmon\JsonApi\Traits\StoreResourceTrait; +use Netmon\JsonApi\Traits\CollectionResourceTrait; abstract class DefaultResourceController extends JsonApiController { diff --git a/src/Http/Controllers/DocumentResourceController.php b/src/Http/Controllers/DocumentResourceController.php index c005a89..fd16ec9 100644 --- a/src/Http/Controllers/DocumentResourceController.php +++ b/src/Http/Controllers/DocumentResourceController.php @@ -1,8 +1,8 @@ <?php -namespace Netmon\Server\App\Http\Controllers\JsonApi; +namespace Netmon\JsonApi\Http\Controllers\JsonApi; -use Netmon\Server\App\Traits\DocumentResourceTrait; +use Netmon\JsonApi\Traits\DocumentResourceTrait; abstract class DocumentResourceController extends JsonApiController { diff --git a/src/Http/Controllers/JsonApiController.php b/src/Http/Controllers/JsonApiController.php index 389556f..67b4367 100644 --- a/src/Http/Controllers/JsonApiController.php +++ b/src/Http/Controllers/JsonApiController.php @@ -1,6 +1,6 @@ <?php -namespace Netmon\Server\App\Http\Controllers\JsonApi; +namespace Netmon\JsonApi\Http\Controllers\JsonApi; use Illuminate\Routing\Controller; diff --git a/src/Http/Controllers/OneToOneResourceController.php b/src/Http/Controllers/OneToOneResourceController.php index 089f106..3f8fba3 100644 --- a/src/Http/Controllers/OneToOneResourceController.php +++ b/src/Http/Controllers/OneToOneResourceController.php @@ -1,8 +1,8 @@ <?php -namespace Netmon\Server\App\Http\Controllers\JsonApi; +namespace Netmon\JsonApi\Http\Controllers\JsonApi; -use Netmon\Server\App\Traits\StoreResourceTrait; +use Netmon\JsonApi\Traits\StoreResourceTrait; abstract class OneToOneResourceController extends JsonApiController { diff --git a/src/Serializers/BasicSerializer.php b/src/Serializers/BasicSerializer.php index a9cfc28..178c741 100644 --- a/src/Serializers/BasicSerializer.php +++ b/src/Serializers/BasicSerializer.php @@ -1,4 +1,4 @@ -<?php namespace Netmon\Server\App\Serializers; +<?php namespace Netmon\JsonApi\Serializers; use Illuminate\Contracts\Container\Container; use DateTime; diff --git a/src/Traits/CollectionResourceTrait.php b/src/Traits/CollectionResourceTrait.php index 76c77f5..d011ecb 100644 --- a/src/Traits/CollectionResourceTrait.php +++ b/src/Traits/CollectionResourceTrait.php @@ -1,6 +1,6 @@ <?php -namespace Netmon\Server\App\Traits; +namespace Netmon\JsonApi\Traits; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; diff --git a/src/Traits/DocumentResourceTrait.php b/src/Traits/DocumentResourceTrait.php index 630316f..ec685ec 100644 --- a/src/Traits/DocumentResourceTrait.php +++ b/src/Traits/DocumentResourceTrait.php @@ -1,6 +1,6 @@ <?php -namespace Netmon\Server\App\Traits; +namespace Netmon\JsonApi\Traits; use Gate; diff --git a/src/Traits/StoreResourceTrait.php b/src/Traits/StoreResourceTrait.php index f351c7e..d8f432c 100644 --- a/src/Traits/StoreResourceTrait.php +++ b/src/Traits/StoreResourceTrait.php @@ -1,8 +1,8 @@ <?php -namespace Netmon\Server\App\Traits; +namespace Netmon\JsonApi\Traits; -use Netmon\Server\App\Exceptions\Exceptions\BodyValidationException; +use Netmon\JsonApi\Exceptions\Exceptions\BodyValidationException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -42,10 +42,10 @@ trait StoreResourceTrait { $requestBody = $request->getContent(); $requestBodyObject = json_decode($requestBody); - $jsonBaseSchema = file_get_contents(resource_path('schemas/schema')); + $jsonBaseSchema = file_get_contents(base_path('vendor/netmon-server/laravel-jsonapi/resources/schemas/schema')); $jsonBaseSchemaObject = json_decode($jsonBaseSchema); - $jsonCreateSchema = file_get_contents(resource_path('schemas/schema-create')); + $jsonCreateSchema = file_get_contents(base_path('vendor/netmon-server/laravel-jsonapi/resources/schemas/schema')); $jsonCreateSchemaObject = json_decode($jsonCreateSchema); // The SchemaStorage can resolve references, loading additional schemas from file as needed, etc. -- GitLab