Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/EchoIt/JsonApi/Exception/Validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php namespace EchoIt\JsonApi\Exception;

use EchoIt\JsonApi\Exception;
use EchoIt\JsonApi\MultiErrorResponse;
use Illuminate\Support\MessageBag as ValidationMessages;

/**
* Validation represents an Exception that can be thrown in the event of a validation failure where a JSON response may be expected.
*
* @author Matt <matt@ninjapenguin.co.uk>
*/
class Validation extends Exception
{
protected $httpStatusCode;
protected $validationMessages;

/**
* Constructor.
*
* @param string $message The Exception message to throw
* @param int $code The Exception code
* @param int $httpStatusCode HTTP status code which can be used for broken request
* @param Illuminate\Support\MessageBag $messages Validation errors
*/
public function __construct($message = '', $code = 0, $httpStatusCode = 500, ValidationMessages $messages = NULL)
{
parent::__construct($message, $code);

$this->httpStatusCode = $httpStatusCode;
$this->validationMessages = $messages;
}

/**
* This method returns a HTTP response representation of the Exception
*
* @return JsonApi\MultiErrorResponse
*/
public function response()
{
return new MultiErrorResponse($this->httpStatusCode, $this->code, $this->message, $this->validationMessages);
}
}
29 changes: 29 additions & 0 deletions src/EchoIt/JsonApi/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,33 @@ protected function handleGetDefault(Request $request, $model)
return $results;
}

/**
* Validates passed data against a model
* Validation performed safely and only if model provides rules
*
* @param EchoIt\JsonApi\Model $model model to validate against
* @param Array $values passed array of values
*
* @throws Exception\Validation Exception thrown when validation fails
*
* @return Bool true if validation successful
*/
protected function validateModelData(Model $model, Array $values)
{
$validationResponse = $model->validateArray($values);

if ($validationResponse === true) {
return true;
}

throw new Exception\Validation(
'Bad Request',
static::ERROR_SCOPE | static::ERROR_HTTP_METHOD_NOT_ALLOWED,
BaseResponse::HTTP_BAD_REQUEST,
$validationResponse
);
}

/**
* Default handling of POST request.
* Must be called explicitly in handlePost function.
Expand All @@ -537,6 +564,8 @@ protected function handleGetDefault(Request $request, $model)
public function handlePostDefault(Request $request, $model)
{
$values = $this->parseRequestContent($request->content, $model->getResourceType());
$this->validateModelData($model, $values);

$model->fill($values);

if (!$model->save()) {
Expand Down
32 changes: 32 additions & 0 deletions src/EchoIt/JsonApi/Model.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace EchoIt\JsonApi;

use Validator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as BaseModel;
use Illuminate\Database\Eloquent\Relations\Pivot as Pivot;
Expand Down Expand Up @@ -121,6 +122,37 @@ public function getResourceType()
return ($this->resourceType ?: $this->getTable());
}

/**
* Validate passed values
*
* @param Array $values user passed values (request data)
*
* @return bool|Illuminate\Support\MessageBag True on pass, MessageBag of errors on fail
*/
public function validateArray(Array $values)
{
if (count($this->getValidationRules())) {
$validator = Validator::make($values, $this->getValidationRules());

if ($validator->fails()) {
return $validator->errors();
}
}

return True;
}

/**
* Return model validation rules
* Models should overload this to provide their validation rules
*
* @return Array validation rules
*/
public function getValidationRules()
{
return [];
}

/**
* Convert the model instance to an array. This method overrides that of
* Eloquent to prevent relations to be serialize into output array.
Expand Down
39 changes: 39 additions & 0 deletions src/EchoIt/JsonApi/MultiErrorResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php namespace EchoIt\JsonApi;

use Illuminate\Http\JsonResponse;
use Illuminate\Support\MessageBag as ValidationMessages;

/**
* MultiErrorResponse represents a HTTP error response containing multiple errors with a JSON API compliant payload.
*
* @author Matt <matt@ninjapenguin.co.uk>
*/
class MultiErrorResponse extends JsonResponse
{
/**
* Constructor.
*
* @param int $httpStatusCode HTTP status code
* @param mixed $errorCode Internal error code
* @param string $errorTitle Error description
* @param Illuminate\Support\MessageBag $errors Validation errors
*/
public function __construct($httpStatusCode, $errorCode, $errorTitle, ValidationMessages $errors = NULL)
{
$data = [ 'errors' => [] ];

if ($errors) {
foreach ($errors->keys() as $field) {

foreach ($errors->get($field) as $message) {

$data['errors'][] = [ 'status' => $httpStatusCode, 'code' => $errorCode, 'title' => 'Validation Fail', 'detail' => $message, 'meta' => ['field' => $field] ];

}

}
}

parent::__construct($data, $httpStatusCode);
}
}