Skip to content

Commit 528c764

Browse files
committed
Make resolved create/update data available in Context
1 parent a510850 commit 528c764

File tree

7 files changed

+54
-40
lines changed

7 files changed

+54
-40
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ and this project adheres to
8383
identifier objects in linkage
8484
- Add static `Field::location(): string` method to determine where fields appear
8585
in JSON:API documents (`attributes`, `relationships`, or root level for `id`)
86+
- Add `Context::$data` to access resolved create/update data in callbacks
8687

8788
### Changed
8889

docs/context.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class Context
3434
// The model that is currently being serialized, updated, or deleted
3535
public object $model = null;
3636

37+
// The resolved data that is being processed for update/delete
38+
public ?array $data = null;
39+
3740
// The field that is currently being processed
3841
public ?Field $field = null;
3942

src/Context.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Context
2525
public ?object $query = null;
2626
public ?Serializer $serializer = null;
2727
public ?object $model = null;
28+
public ?array $data = null;
2829
public ?Field $field = null;
2930
public ?array $include = null;
3031
public ArrayObject $documentMeta;
@@ -317,6 +318,13 @@ public function withBody(?array $body): static
317318
return $new;
318319
}
319320

321+
public function withData(?array $data): static
322+
{
323+
$new = clone $this;
324+
$new->data = $data;
325+
return $new;
326+
}
327+
320328
public function withCollection(?Collection $collection): static
321329
{
322330
$new = clone $this;

src/Endpoint/Concerns/SavesData.php

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,21 @@ private function getFields(Context $context, bool $creating = false): array
9696
/**
9797
* Assert that the fields contained within a data object are valid.
9898
*/
99-
private function assertFieldsValid(Context $context, array $data, bool $creating = false): void
99+
private function assertFieldsValid(Context $context, bool $creating = false): void
100100
{
101-
$this->assertFieldsExist($context, $data);
102-
$this->assertFieldsWritable($context, $data, $creating);
101+
$this->assertFieldsExist($context);
102+
$this->assertFieldsWritable($context, $creating);
103103
}
104104

105105
/**
106106
* Assert that the fields contained within a data object exist in the schema.
107107
*/
108-
private function assertFieldsExist(Context $context, array $data): void
108+
private function assertFieldsExist(Context $context): void
109109
{
110110
$fields = $this->getFields($context);
111111

112112
foreach (['attributes', 'relationships'] as $location) {
113-
foreach ($data[$location] as $name => $value) {
113+
foreach ($context->data[$location] as $name => $value) {
114114
if (!isset($fields[$name]) || $location !== $fields[$name]->location()) {
115115
throw (new UnknownFieldException($name))->source([
116116
'pointer' => '/data/' . implode('/', array_filter([$location, $name])),
@@ -125,13 +125,10 @@ private function assertFieldsExist(Context $context, array $data): void
125125
*
126126
* @throws ForbiddenException if a field is not writable.
127127
*/
128-
private function assertFieldsWritable(
129-
Context $context,
130-
array $data,
131-
bool $creating = false,
132-
): void {
128+
private function assertFieldsWritable(Context $context, bool $creating = false): void
129+
{
133130
foreach ($this->getFields($context, $creating) as $field) {
134-
if (!has_value($data, $field)) {
131+
if (!has_value($context->data, $field)) {
135132
continue;
136133
}
137134

@@ -160,17 +157,17 @@ private function assertFieldWritable(
160157
/**
161158
*
162159
*/
163-
private function deserializeValues(Context $context, array &$data, bool $creating = false): void
160+
private function deserializeValues(Context $context, bool $creating = false): void
164161
{
165162
foreach ($this->getFields($context, $creating) as $field) {
166-
if (!has_value($data, $field)) {
163+
if (!has_value($context->data, $field)) {
167164
continue;
168165
}
169166

170-
$value = get_value($data, $field);
167+
$value = get_value($context->data, $field);
171168

172169
try {
173-
set_value($data, $field, $field->deserializeValue($value, $context));
170+
set_value($context->data, $field, $field->deserializeValue($value, $context));
174171
} catch (Sourceable $e) {
175172
throw $e->prependSource(['pointer' => '/data' . field_path($field)]);
176173
}
@@ -182,12 +179,12 @@ private function deserializeValues(Context $context, array &$data, bool $creatin
182179
*
183180
* @throws JsonApiErrorsException if any fields do not pass validation.
184181
*/
185-
private function assertDataValid(Context $context, array $data, bool $validateAll): void
182+
private function assertDataValid(Context $context, bool $validateAll): void
186183
{
187184
$errors = [];
188185

189186
foreach ($this->getFields($context, $validateAll) as $field) {
190-
$present = has_value($data, $field);
187+
$present = has_value($context->data, $field);
191188

192189
if (!$present && (!$field->required || !$validateAll)) {
193190
continue;
@@ -200,7 +197,7 @@ private function assertDataValid(Context $context, array $data, bool $validateAl
200197
} else {
201198
array_push(
202199
$errors,
203-
...$this->validateField($context, $field, get_value($data, $field)),
200+
...$this->validateField($context, $field, get_value($context->data, $field)),
204201
);
205202
}
206203
}
@@ -232,14 +229,14 @@ private function validateField(Context $context, Field|Id $field, mixed $value):
232229
/**
233230
* Set field values from a data object to the model instance.
234231
*/
235-
private function setValues(Context $context, array $data, bool $creating = false): void
232+
private function setValues(Context $context, bool $creating = false): void
236233
{
237234
foreach ($this->getFields($context, $creating) as $field) {
238-
if (!has_value($data, $field)) {
235+
if (!has_value($context->data, $field)) {
239236
continue;
240237
}
241238

242-
$value = get_value($data, $field);
239+
$value = get_value($context->data, $field);
243240

244241
$field->setValue($context->model, $value, $context);
245242
}
@@ -248,14 +245,14 @@ private function setValues(Context $context, array $data, bool $creating = false
248245
/**
249246
* Run any field save callbacks.
250247
*/
251-
private function saveFields(Context $context, array $data, bool $creating = false): void
248+
private function saveFields(Context $context, bool $creating = false): void
252249
{
253250
foreach ($this->getFields($context, $creating) as $field) {
254-
if (!has_value($data, $field)) {
251+
if (!has_value($context->data, $field)) {
255252
continue;
256253
}
257254

258-
$value = get_value($data, $field);
255+
$value = get_value($context->data, $field);
259256

260257
$field->saveValue($context->model, $value, $context);
261258
}

src/Endpoint/Create.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,14 @@ public function handle(Context $context): ?ResponseInterface
6969

7070
$context = $context
7171
->withResource($resource = $context->resource($data['type']))
72-
->withModel($model = $collection->newModel($context));
72+
->withModel($model = $collection->newModel($context))
73+
->withData($data);
7374

74-
$this->assertFieldsValid($context, $data, true);
75-
$this->fillDefaultValues($context, $data);
76-
$this->deserializeValues($context, $data, true);
77-
$this->assertDataValid($context, $data, true);
78-
$this->setValues($context, $data, true);
75+
$this->assertFieldsValid($context, true);
76+
$this->fillDefaultValues($context);
77+
$this->deserializeValues($context, true);
78+
$this->assertDataValid($context, true);
79+
$this->setValues($context, true);
7980

8081
if ($this->asyncCallback) {
8182
$asyncResult = ($this->asyncCallback)($model, $context);
@@ -109,7 +110,7 @@ public function handle(Context $context): ?ResponseInterface
109110

110111
$context = $context->withModel($model = $resource->create($model, $context));
111112

112-
$this->saveFields($context, $data, true);
113+
$this->saveFields($context, true);
113114

114115
$response = $context
115116
->createResponse($document = $this->buildResourceDocument($model, $context))
@@ -130,11 +131,11 @@ public function async(string $collection, Closure $callback): static
130131
return $this;
131132
}
132133

133-
private function fillDefaultValues(Context $context, array &$data): void
134+
private function fillDefaultValues(Context $context): void
134135
{
135136
foreach ($this->getFields($context, true) as $field) {
136-
if (!has_value($data, $field) && ($default = $field->default)) {
137-
set_value($data, $field, $default($context->withField($field)));
137+
if (!has_value($context->data, $field) && ($default = $field->default)) {
138+
set_value($context->data, $field, $default($context->withField($field)));
138139
}
139140
}
140141
}

src/Endpoint/Update.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,16 @@ private function updateResource(
264264
): ResponseInterface {
265265
$data = $this->parseData($context);
266266

267-
$this->assertFieldsValid($context, $data);
268-
$this->deserializeValues($context, $data);
269-
$this->assertDataValid($context, $data, false);
270-
$this->setValues($context, $data);
267+
$context = $context->withData($data);
268+
269+
$this->assertFieldsValid($context);
270+
$this->deserializeValues($context);
271+
$this->assertDataValid($context, false);
272+
$this->setValues($context);
271273

272274
$context = $context->withModel($model = $resource->update($model, $context));
273275

274-
$this->saveFields($context, $data);
276+
$this->saveFields($context);
275277

276278
$response = $context->createResponse($this->buildResourceDocument($model, $context));
277279

src/Laravel/functions.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ function rules($rules, array $messages = [], array $customAttributes = []): Clos
3737
}
3838

3939
$validation = Validator::make(
40-
$value !== null ? [$key => $value] : [],
40+
$value !== null
41+
? [$key => $value]
42+
: [] + $context->data['attributes'] + $context->data['relationships'],
4143
$validatorRules,
4244
$messages,
4345
$customAttributes,

0 commit comments

Comments
 (0)