Skip to content

Commit 0a892da

Browse files
authored
Use custom attachers (#197)
* Use custom attachers * Apply fixes from StyleCI (#196)
1 parent 208dde4 commit 0a892da

File tree

9 files changed

+181
-3
lines changed

9 files changed

+181
-3
lines changed

src/Http/Controllers/RepositoryAttachController.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
use Binaryk\LaravelRestify\Http\Requests\RepositoryAttachRequest;
66
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
7+
use Binaryk\LaravelRestify\Repositories\Repository;
78
use DateTime;
89
use Illuminate\Support\Arr;
10+
use Illuminate\Support\Str;
911

1012
class RepositoryAttachController extends RepositoryController
1113
{
@@ -14,12 +16,16 @@ public function __invoke(RepositoryAttachRequest $request)
1416
$model = $request->findModelOrFail();
1517
$repository = $request->repository()->allowToUpdate($request);
1618

19+
if (is_callable($method = $this->guessMethodName($request, $repository))) {
20+
return call_user_func($method, $request, $repository, $model);
21+
}
22+
1723
return $repository->attach(
1824
$request, $request->repositoryId,
1925
collect(Arr::wrap($request->input($request->relatedRepository)))
20-
->map(fn ($relatedRepositoryId) => $this->initializePivot(
21-
$request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId
22-
))
26+
->map(fn ($relatedRepositoryId) => $this->initializePivot(
27+
$request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId
28+
))
2329
);
2430
}
2531

@@ -61,4 +67,21 @@ protected function initializePivot(RestifyRequest $request, $relationship, $rela
6167

6268
return $pivot;
6369
}
70+
71+
public function guessMethodName(RestifyRequest $request, Repository $repository): ?callable
72+
{
73+
$key = $request->relatedRepository;
74+
75+
if (array_key_exists($key, $repository::getAttachers()) && is_callable($cb = $repository::getAttachers()[$key])) {
76+
return $cb;
77+
}
78+
79+
$methodGuesser = 'attach'.Str::studly($request->relatedRepository);
80+
81+
if (method_exists($repository, $methodGuesser)) {
82+
return [$repository, $methodGuesser];
83+
}
84+
85+
return null;
86+
}
6487
}

src/Repositories/Repository.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ abstract class Repository implements RestifySearchable, JsonSerializable
104104
*/
105105
public static $middlewares = [];
106106

107+
/**
108+
* The list of attach callable's.
109+
*
110+
* @var array
111+
*/
112+
public static $attachers = [];
113+
107114
/**
108115
* Get the underlying model instance for the resource.
109116
*
@@ -743,4 +750,9 @@ public static function collectMiddlewares(RestifyRequest $request): ?Collection
743750
{
744751
return collect(static::$middlewares);
745752
}
753+
754+
public static function getAttachers(): array
755+
{
756+
return static::$attachers;
757+
}
746758
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Controllers;
4+
5+
use Binaryk\LaravelRestify\Tests\Fixtures\Role\Role;
6+
use Binaryk\LaravelRestify\Tests\IntegrationTest;
7+
8+
class RepositoryAttachInterceptorTest extends IntegrationTest
9+
{
10+
public function test_can_intercept_attach_method()
11+
{
12+
$role = factory(Role::class)->create();
13+
$user = $this->mockUsers()->first();
14+
15+
$this->postJson('restify-api/roles/'.$role->id.'/attach/users', [
16+
'users' => $user->id,
17+
])
18+
->assertCreated();
19+
20+
$this->assertDatabaseCount('model_has_roles', 1);
21+
}
22+
}

tests/Factories/Roleactory.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
use Binaryk\LaravelRestify\Tests\Fixtures\Role\Role;
4+
use Faker\Generator as Faker;
5+
6+
/*
7+
|--------------------------------------------------------------------------
8+
| Model Factories
9+
|--------------------------------------------------------------------------
10+
|
11+
| This directory should contain each of the model factory definitions for
12+
| your application. Factories provide a convenient way to generate new
13+
| model instances for testing / seeding your application's database.
14+
|
15+
*/
16+
17+
$factory->define(Role::class, function (Faker $faker) {
18+
return [
19+
'name' => $faker->word,
20+
'guard_name' => 'web',
21+
];
22+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class ModelHasRole extends Model
8+
{
9+
public $timestamps = false;
10+
11+
protected $table = 'model_has_roles';
12+
13+
protected $guarded = ['id'];
14+
}

tests/Fixtures/Role/Role.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class Role extends Model
8+
{
9+
protected $table = 'roles';
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;
4+
5+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
6+
use Binaryk\LaravelRestify\Repositories\Repository;
7+
use Binaryk\LaravelRestify\Tests\Fixtures\User\User;
8+
use Illuminate\Database\Eloquent\Model;
9+
10+
class RoleRepository extends Repository
11+
{
12+
public static $model = Role::class;
13+
14+
public function attachUsers(RestifyRequest $request, Repository $repository, Model $model)
15+
{
16+
ModelHasRole::create([
17+
'role_id' => $model->id,
18+
'model_type' => User::class,
19+
'model_id' => $request->get('users'),
20+
]);
21+
22+
return $this->response()->created();
23+
}
24+
}

tests/IntegrationTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostUnauthorizedFieldRepository;
1414
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithHiddenFieldRepository;
1515
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithUnauthorizedFieldsRepository;
16+
use Binaryk\LaravelRestify\Tests\Fixtures\Role\RoleRepository;
1617
use Binaryk\LaravelRestify\Tests\Fixtures\User\User;
1718
use Binaryk\LaravelRestify\Tests\Fixtures\User\UserRepository;
1819
use Illuminate\Contracts\Auth\Authenticatable;
@@ -188,6 +189,7 @@ public function loadRepositories()
188189
PostWithUnauthorizedFieldsRepository::class,
189190
PostUnauthorizedFieldRepository::class,
190191
PostWithHiddenFieldRepository::class,
192+
RoleRepository::class,
191193
]);
192194
}
193195

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class CreateRolesTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('roles', function (Blueprint $table) {
17+
$table->bigIncrements('id');
18+
$table->string('name');
19+
$table->string('guard_name');
20+
$table->timestamps();
21+
});
22+
23+
Schema::create('model_has_roles', function (Blueprint $table) {
24+
$table->unsignedBigInteger('role_id');
25+
26+
$table->string('model_type');
27+
$table->unsignedBigInteger('model_id');
28+
$table->index(['model_id', 'model_type'], 'model_has_roles_model_id_model_type_index');
29+
30+
$table->foreign('role_id')
31+
->references('id')
32+
->on('roles')
33+
->onDelete('cascade');
34+
35+
$table->primary(['role_id', 'model_id', 'model_type'],
36+
'model_has_roles_role_model_type_primary');
37+
});
38+
}
39+
40+
/**
41+
* Reverse the migrations.
42+
*
43+
* @return void
44+
*/
45+
public function down()
46+
{
47+
Schema::dropIfExists('roles');
48+
}
49+
}

0 commit comments

Comments
 (0)