From 79682fa1a17fa827a8032c537655009de4b2ac84 Mon Sep 17 00:00:00 2001 From: Diana Sindrilaru Date: Wed, 17 Nov 2021 09:59:16 +0200 Subject: [PATCH 1/2] Use actionable fields in bulk requests --- src/Fields/FieldCollection.php | 11 +++++++---- src/Repositories/Repository.php | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Fields/FieldCollection.php b/src/Fields/FieldCollection.php index 83ae188ad..07f4d081f 100644 --- a/src/Fields/FieldCollection.php +++ b/src/Fields/FieldCollection.php @@ -78,10 +78,10 @@ public function forStore(RestifyRequest $request, $repository): self })->values(); } - public function withActions(RestifyRequest $request, $repository): self + public function withActions(RestifyRequest $request, $repository, $row = null): self { return $this - ->inRequest($request) + ->inRequest($request, $row) ->filter(fn (Field $field) => $field->isActionable()) ->values(); } @@ -154,10 +154,13 @@ public function findFieldByAttribute($attribute, $default = null) return null; } - public function inRequest(RestifyRequest $request): self + public function inRequest(RestifyRequest $request, $row = null): self { return $this - ->filter(fn (Field $field) => $request->has($field->attribute) || $request->hasFile($field->attribute)) + ->filter(fn (Field $field) => + $request->hasAny($field->attribute, $row.'.'.$field->attribute) + || $request->hasFile($field->attribute) + ) ->values(); } } diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index ccbfc3268..647c1ff9a 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -672,6 +672,7 @@ public function storeBulk(RepositoryStoreBulkRequest $request) $this->resource, $fields = $this->collectFields($request) ->forStoreBulk($request, $this) + ->withoutActions($request, $this) ->authorizedUpdateBulk($request), $row ); @@ -680,6 +681,13 @@ public function storeBulk(RepositoryStoreBulkRequest $request) $fields->each(fn (Field $field) => $field->invokeAfter($request, $this->resource)); + $this + ->collectFields($request) + ->forStoreBulk($request, $this) + ->withActions($request, $this, $row) + ->authorizedUpdateBulk($request) + ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource)); + return $this->resource; }); }); @@ -764,12 +772,20 @@ public function updateBulk(RestifyRequest $request, $repositoryId, int $row) { $fields = $this->collectFields($request) ->forUpdateBulk($request, $this) + ->withoutActions($request, $this) ->authorizedUpdateBulk($request); static::fillBulkFields($request, $this->resource, $fields, $row); $this->resource->save(); + $this + ->collectFields($request) + ->forUpdateBulk($request, $this) + ->withActions($request, $this, $row) + ->authorizedUpdateBulk($request) + ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource)); + static::updatedBulk($this->resource, $request); return response()->json(); From c067f1a01bad1cb5ee96532896f03e219267ea56 Mon Sep 17 00:00:00 2001 From: Diana Sindrilaru Date: Wed, 17 Nov 2021 13:17:20 +0200 Subject: [PATCH 2/2] Add tests for actionable fields on bulk requests --- src/Actions/Action.php | 2 +- src/Repositories/Repository.php | 4 +- tests/Actions/FieldActionTest.php | 106 ++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) diff --git a/src/Actions/Action.php b/src/Actions/Action.php index 84c4607c5..f551d559d 100644 --- a/src/Actions/Action.php +++ b/src/Actions/Action.php @@ -22,7 +22,7 @@ /** * Class Action - * @method JsonResponse handle(Request $request, Model|Collection $models) + * @method JsonResponse handle(Request $request, Model|Collection $models, ?int $row) * @package Binaryk\LaravelRestify\Actions */ abstract class Action implements JsonSerializable diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index 647c1ff9a..203bc1020 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -686,7 +686,7 @@ public function storeBulk(RepositoryStoreBulkRequest $request) ->forStoreBulk($request, $this) ->withActions($request, $this, $row) ->authorizedUpdateBulk($request) - ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource)); + ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource, $row)); return $this->resource; }); @@ -784,7 +784,7 @@ public function updateBulk(RestifyRequest $request, $repositoryId, int $row) ->forUpdateBulk($request, $this) ->withActions($request, $this, $row) ->authorizedUpdateBulk($request) - ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource)); + ->each(fn (Field $field) => $field->actionHandler->handle($request, $this->resource, $row)); static::updatedBulk($this->resource, $request); diff --git a/tests/Actions/FieldActionTest.php b/tests/Actions/FieldActionTest.php index 913e9b00f..99d7d1499 100644 --- a/tests/Actions/FieldActionTest.php +++ b/tests/Actions/FieldActionTest.php @@ -49,4 +49,110 @@ public function handle(RestifyRequest $request, Post $post) ->etc() ); } + + /** @test */ + public function can_use_actionable_field_on_bulk_store(): void + { + $action = new class extends Action { + public bool $showOnShow = true; + + public function handle(RestifyRequest $request, Post $post, int $row) + { + $description = data_get($request[$row], 'description'); + + $post->update([ + 'description' => 'Actionable ' . $description, + ]); + } + }; + + PostRepository::partialMock() + ->shouldReceive('fieldsForStoreBulk') + ->andreturn([ + Field::new('title'), + + Field::new('description')->action($action), + ]); + + $this + ->withoutExceptionHandling() + ->postJson(PostRepository::to('bulk'), [ + [ + 'title' => $title1 = 'First title', + 'description' => 'first description', + ], + [ + 'title' => $title2 = 'Second title', + 'description' => 'second description', + ], + ]) + ->assertJson( + fn (AssertableJson $json) => $json + ->where('data.0.title', $title1) + ->where('data.0.description', 'Actionable first description') + ->where('data.1.title', $title2) + ->where('data.1.description', 'Actionable second description') + ->etc() + ); + } + + /** @test */ + public function can_use_actionable_field_on_bulk_update(): void + { + $action = new class extends Action { + public bool $showOnShow = true; + + public function handle(RestifyRequest $request, Post $post, int $row) + { + $description = data_get($request[$row], 'description'); + + $post->update([ + 'description' => 'Actionable ' . $description, + ]); + } + }; + + PostRepository::partialMock() + ->shouldReceive('fieldsForUpdateBulk') + ->andreturn([ + Field::new('title'), + + Field::new('description')->action($action), + ]); + + $postId1 = $this + ->withoutExceptionHandling() + ->postJson(PostRepository::to(), [ + 'title' => 'First title', + ])->json('data.id'); + + $postId2 = $this + ->withoutExceptionHandling() + ->postJson(PostRepository::to(), [ + 'title' => 'Second title', + ])->json('data.id'); + + $this + ->withoutExceptionHandling() + ->postJson(PostRepository::to('bulk/update'), [ + [ + 'id' => $postId1, + 'description' => 'first description', + ], + [ + 'id' => $postId2, + 'description' => 'second description', + ], + ])->assertOk(); + + $this->assertSame( + 'Actionable first description', + Post::find($postId1)->description + ); + + $this->assertSame( + 'Actionable second description', + Post::find($postId2)->description + ); + } }