8000 [Refactor] Improve providing existing values to resource validator · AxonDivisionDev/laravel-json-api@549f91c · GitHub
[go: up one dir, main page]

Skip to content

Commit 549f91c

Browse files
committed
[Refactor] Improve providing existing values to resource validator
Closes cloudcreativity#246
1 parent 7e98897 commit 549f91c

File tree

3 files changed

+90
-12
lines changed

3 files changed

+90
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ All notable changes to this project will be documented in this file. This projec
77
### Added
88
- [#247](https://github.com/cloudcreativity/laravel-json-api/issues/247)
99
New date time rule object to validate a JSON date string is a valid ISO 8601 date and time format.
10+
- [#246](https://github.com/cloudcreativity/laravel-json-api/issues/246)
11+
Can now disable providing the existing resource attributes to the resource validator for an update
12+
request.
13+
- Added an `existingRelationships` method to the abstract validators class. Child classes can overload
14+
this method if they need the validator to have access to any existing relationship values for an
15+
update request.
1016

1117
### Changed
1218
- [#248](https://github.com/cloudcreativity/laravel-json-api/pull/248)

docs/basics/validators.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ the client, your validator will be provided with the following array of data:
263263
> We use your resource schema's `getAttributes` method to obtain the existing attribute values.
264264
265265
There is no reliable way for us to work out the existing values of any relationships that were missing in
266-
the request document. If you need to add any existing values, you can do this as follows:
266+
the request document. If you need to add any existing relationship values, you can do this by returning
267+
the relationships in their JSON API form. For example:
267268

268269
```php
269270
class Validators extends AbstractValidators
@@ -274,14 +275,24 @@ class Validators extends AbstractValidators
274275
* @param \App\Post $record
275276
* @return \Illuminate\Support\Collection
276277
*/
277-
protected function existingValues($record): Collection
278+
protected function existingRelationships($record): Collection
278279
{
279-
return parent::existingValues($record)
280-
->put('author', ['type' => 'users', 'id' => $record->user_id]);
280+
return [
281+
'author' => [
282+
'data' => [
283+
'type' => 'users',
284+
'id' => (string) $record->user_id,
285+
],
286+
],
287+
];
281288
}
282289
}
283290
```
284291

292+
If you need to disable the merging of the existing values, set the `$validateExisting` property
293+
of your validators class to `false`. If you need to programmatically work out whether to merge the existing
294+
values, overload the `mustValidateExisting()` method.
295+
285296
### Defining Rules
286297

287298
Define resource object validation rules in your validators `rules` method.

src/Validation/AbstractValidators.php

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ abstract class AbstractValidators implements ValidatorFactoryInterface
121121
*/
122122
protected $allowedFieldSets = null;
123123

124+
/**
125+
* Whether existing resource attributes should be validated on for an update.
126+
*
127+
* If this is set to false, the validator instance will not be provided with the
128+
* resource's existing attribute values when validating an update (PATCH) request.
129+
*
130+
* @var bool
131+
*/
132+
protected $validateExisting = true;
133+
124134
/**
125135
* @var Factory
126136
*/
@@ -303,7 +313,7 @@ protected function createData(array $document): array
303313
* > attributes as null values.
304314
*
305315
* So that the validator has access to the current values of attributes, we
306-
* merge to provided new attributes over the top of the existing attribute
316+
* merge attributes provided by the client over the top of the existing attribute
307317
* values.
308318
*
309319
* @param mixed $record
@@ -316,14 +326,38 @@ protected function updateData($record, array $document): array
316326
{
317327
$resource = $document['data'];
318328

319-
$resource['attributes'] = $this->extractAttributes(
320-
$record,
321-
isset($resource['attributes']) ? $resource['attributes'] : []
322-
)->all();
329+
if ($this->mustValidateExisting($record, $document)) {
330+
$resource['attributes'] = $this->extractAttributes(
331+
$record,
332+
$resource['attributes'] ?? []
333+
)->all();
334+
335+
$resource['relationships'] = $this->extractRelationships(
336+
$record,
337+
$resource['relationships'] ?? []
338+
)->all();
339+
}
323340

324341
return $resource;
325342
}
326343

344+
/**
345+
* Should existing resource values be provided to the validator for an update request?
346+
*
347+
* Child classes can overload this method if they need to programmatically work out
348+
* if existing values must be provided to the validator instance for an update request.
349+
*
350+
* @param mixed $record
351+
* the record being updated
352+
* @param array $document
353+
* the JSON API document provided by the client.
354+
* @return bool
355+
*/
356+
protected function mustValidateExisting($record, array $document): bool
357+
{
358+
return false !== $this->validateExisting;
359+
}
360+
327361
/**
328362
* Extract attributes for a resource update.
329363
*
@@ -333,20 +367,47 @@ protected function updateData($record, array $document): array
333367
*/
334368
protected function extractAttributes($record, array $new): Collection
335369
{
336-
return $this->existingValues($record)->merge($new);
370+
return $this->existingAttributes($record)->merge($new);
337371
}
338372

339373
/**
340-
* Get any existing values for the provided record.
374+
* Get any existing attributes for the provided record.
341375
*
342376
* @param $record
343377
* @return Collection
344378
*/
345-
protected function existingValues($record): Collection
379+
protected function existingAttributes($record): Collection
346380
{
347381
return collect($this->container->getSchema($record)->getAttributes($record));
348382
}
349383

384+
/**
385+
* Extract relationships for a resource update.
386+
*
387+
* @param $record
388+
* @param array $new
389+
* @return Collection
390+
*/
391+
protected function extractRelationships($record, array $new): Collection
392+
{
393+
return $this->existingRelationships($record)->merge($new);
394+
}
395+
396+
/**
397+
* Get any existing relationships for the provided record.
398+
*
399+
* As there is no reliable way for us to work this out (as we do not
400+
* know the relationship keys), child classes should overload this method
401+
* to add existing relationship data.
402+
*
403+
* @param $record
404+
* @return Collection
405+
*/
406+
protected function existingRelationships($record): Collection
407+
{
408+
return collect();
409+
}
410+
350411
/**
351412
* Get validation data for modifying a relationship.
352413
*

0 commit comments

Comments
 (0)
0