From 78b3cd277f5cabb4e166c5bf33b0f2bbf45129e1 Mon Sep 17 00:00:00 2001 From: Eduard Lupacescu Date: Tue, 9 Jun 2020 23:49:32 +0300 Subject: [PATCH 1/2] Use custom attachers --- .../RepositoryAttachController.php | 29 +++++++++-- src/Repositories/Repository.php | 12 +++++ .../RepositoryAttachInterceptorTest.php | 23 +++++++++ tests/Factories/Roleactory.php | 22 +++++++++ tests/Fixtures/Role/ModelHasRole.php | 14 ++++++ tests/Fixtures/Role/Role.php | 10 ++++ tests/Fixtures/Role/RoleRepository.php | 24 +++++++++ tests/IntegrationTest.php | 2 + .../2019_12_22_000006_create_roles_table.php | 49 +++++++++++++++++++ 9 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 tests/Controllers/RepositoryAttachInterceptorTest.php create mode 100644 tests/Factories/Roleactory.php create mode 100644 tests/Fixtures/Role/ModelHasRole.php create mode 100644 tests/Fixtures/Role/Role.php create mode 100644 tests/Fixtures/Role/RoleRepository.php create mode 100644 tests/Migrations/2019_12_22_000006_create_roles_table.php diff --git a/src/Http/Controllers/RepositoryAttachController.php b/src/Http/Controllers/RepositoryAttachController.php index 41e701a1d..b16301941 100644 --- a/src/Http/Controllers/RepositoryAttachController.php +++ b/src/Http/Controllers/RepositoryAttachController.php @@ -4,8 +4,10 @@ use Binaryk\LaravelRestify\Http\Requests\RepositoryAttachRequest; use Binaryk\LaravelRestify\Http\Requests\RestifyRequest; +use Binaryk\LaravelRestify\Repositories\Repository; use DateTime; use Illuminate\Support\Arr; +use Illuminate\Support\Str; class RepositoryAttachController extends RepositoryController { @@ -14,12 +16,16 @@ public function __invoke(RepositoryAttachRequest $request) $model = $request->findModelOrFail(); $repository = $request->repository()->allowToUpdate($request); + if (is_callable($method = $this->guessMethodName($request, $repository))) { + return call_user_func($method, $request, $repository, $model); + } + return $repository->attach( $request, $request->repositoryId, collect(Arr::wrap($request->input($request->relatedRepository))) - ->map(fn ($relatedRepositoryId) => $this->initializePivot( - $request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId - )) + ->map(fn($relatedRepositoryId) => $this->initializePivot( + $request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId + )) ); } @@ -61,4 +67,21 @@ protected function initializePivot(RestifyRequest $request, $relationship, $rela return $pivot; } + + public function guessMethodName(RestifyRequest $request, Repository $repository): ?callable + { + $key = $request->relatedRepository; + + if (array_key_exists($key, $repository::getAttachers()) && is_callable($cb = $repository::getAttachers()[$key])) { + return $cb; + } + + $methodGuesser = "attach" . Str::studly($request->relatedRepository); + + if (method_exists($repository, $methodGuesser)) { + return [$repository, $methodGuesser]; + } + + return null; + } } diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index eb3c422af..a848f2956 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -104,6 +104,13 @@ abstract class Repository implements RestifySearchable, JsonSerializable */ public static $middlewares = []; + /** + * The list of attach callable's. + * + * @var array + */ + public static $attachers = []; + /** * Get the underlying model instance for the resource. * @@ -743,4 +750,9 @@ public static function collectMiddlewares(RestifyRequest $request): ?Collection { return collect(static::$middlewares); } + + public static function getAttachers(): array + { + return static::$attachers; + } } diff --git a/tests/Controllers/RepositoryAttachInterceptorTest.php b/tests/Controllers/RepositoryAttachInterceptorTest.php new file mode 100644 index 000000000..1ccd3382e --- /dev/null +++ b/tests/Controllers/RepositoryAttachInterceptorTest.php @@ -0,0 +1,23 @@ +create(); + $user = $this->mockUsers()->first(); + + $this->postJson('restify-api/roles/' . $role->id . '/attach/users', [ + 'users' => $user->id, + ]) + ->assertCreated(); + + $this->assertDatabaseCount('model_has_roles', 1); + + } +} diff --git a/tests/Factories/Roleactory.php b/tests/Factories/Roleactory.php new file mode 100644 index 000000000..e631a95cb --- /dev/null +++ b/tests/Factories/Roleactory.php @@ -0,0 +1,22 @@ +define(Role::class, function (Faker $faker) { + return [ + 'name' => $faker->word, + 'guard_name' => 'web', + ]; +}); diff --git a/tests/Fixtures/Role/ModelHasRole.php b/tests/Fixtures/Role/ModelHasRole.php new file mode 100644 index 000000000..9845b2ad7 --- /dev/null +++ b/tests/Fixtures/Role/ModelHasRole.php @@ -0,0 +1,14 @@ + $model->id, + 'model_type' => User::class, + 'model_id' => $request->get('users'), + ]); + + return $this->response()->created(); + } +} diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 4f69f6677..3c4a4d59f 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -13,6 +13,7 @@ use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostUnauthorizedFieldRepository; use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithHiddenFieldRepository; use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithUnauthorizedFieldsRepository; +use Binaryk\LaravelRestify\Tests\Fixtures\Role\RoleRepository; use Binaryk\LaravelRestify\Tests\Fixtures\User\User; use Binaryk\LaravelRestify\Tests\Fixtures\User\UserRepository; use Illuminate\Contracts\Auth\Authenticatable; @@ -188,6 +189,7 @@ public function loadRepositories() PostWithUnauthorizedFieldsRepository::class, PostUnauthorizedFieldRepository::class, PostWithHiddenFieldRepository::class, + RoleRepository::class, ]); } diff --git a/tests/Migrations/2019_12_22_000006_create_roles_table.php b/tests/Migrations/2019_12_22_000006_create_roles_table.php new file mode 100644 index 000000000..28c3f6865 --- /dev/null +++ b/tests/Migrations/2019_12_22_000006_create_roles_table.php @@ -0,0 +1,49 @@ +bigIncrements('id'); + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + }); + + Schema::create('model_has_roles', function (Blueprint $table) { + $table->unsignedBigInteger('role_id'); + + $table->string('model_type'); + $table->unsignedBigInteger('model_id'); + $table->index(['model_id', 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign('role_id') + ->references('id') + ->on('roles') + ->onDelete('cascade'); + + $table->primary(['role_id', 'model_id', 'model_type'], + 'model_has_roles_role_model_type_primary'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('roles'); + } +} From 43a59b69629f9afedc7c9f00105f4e72668bc59c Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Tue, 9 Jun 2020 23:49:58 +0300 Subject: [PATCH 2/2] Apply fixes from StyleCI (#196) --- src/Http/Controllers/RepositoryAttachController.php | 4 ++-- tests/Controllers/RepositoryAttachInterceptorTest.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Http/Controllers/RepositoryAttachController.php b/src/Http/Controllers/RepositoryAttachController.php index b16301941..c25a5eefa 100644 --- a/src/Http/Controllers/RepositoryAttachController.php +++ b/src/Http/Controllers/RepositoryAttachController.php @@ -23,7 +23,7 @@ public function __invoke(RepositoryAttachRequest $request) return $repository->attach( $request, $request->repositoryId, collect(Arr::wrap($request->input($request->relatedRepository))) - ->map(fn($relatedRepositoryId) => $this->initializePivot( + ->map(fn ($relatedRepositoryId) => $this->initializePivot( $request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId )) ); @@ -76,7 +76,7 @@ public function guessMethodName(RestifyRequest $request, Repository $repository) return $cb; } - $methodGuesser = "attach" . Str::studly($request->relatedRepository); + $methodGuesser = 'attach'.Str::studly($request->relatedRepository); if (method_exists($repository, $methodGuesser)) { return [$repository, $methodGuesser]; diff --git a/tests/Controllers/RepositoryAttachInterceptorTest.php b/tests/Controllers/RepositoryAttachInterceptorTest.php index 1ccd3382e..55c2dc590 100644 --- a/tests/Controllers/RepositoryAttachInterceptorTest.php +++ b/tests/Controllers/RepositoryAttachInterceptorTest.php @@ -12,12 +12,11 @@ public function test_can_intercept_attach_method() $role = factory(Role::class)->create(); $user = $this->mockUsers()->first(); - $this->postJson('restify-api/roles/' . $role->id . '/attach/users', [ + $this->postJson('restify-api/roles/'.$role->id.'/attach/users', [ 'users' => $user->id, ]) ->assertCreated(); $this->assertDatabaseCount('model_has_roles', 1); - } }