Skip to content

Commit

Permalink
Use custom attachers (#197)
Browse files Browse the repository at this point in the history
* Use custom attachers

* Apply fixes from StyleCI (#196)
  • Loading branch information
binaryk authored Jun 9, 2020
1 parent 208dde4 commit 0a892da
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/Http/Controllers/RepositoryAttachController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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
))
);
}

Expand Down Expand Up @@ -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;
}
}
12 changes: 12 additions & 0 deletions src/Repositories/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -743,4 +750,9 @@ public static function collectMiddlewares(RestifyRequest $request): ?Collection
{
return collect(static::$middlewares);
}

public static function getAttachers(): array
{
return static::$attachers;
}
}
22 changes: 22 additions & 0 deletions tests/Controllers/RepositoryAttachInterceptorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Controllers;

use Binaryk\LaravelRestify\Tests\Fixtures\Role\Role;
use Binaryk\LaravelRestify\Tests\IntegrationTest;

class RepositoryAttachInterceptorTest extends IntegrationTest
{
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', [
'users' => $user->id,
])
->assertCreated();

$this->assertDatabaseCount('model_has_roles', 1);
}
}
22 changes: 22 additions & 0 deletions tests/Factories/Roleactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Binaryk\LaravelRestify\Tests\Fixtures\Role\Role;
use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(Role::class, function (Faker $faker) {
return [
'name' => $faker->word,
'guard_name' => 'web',
];
});
14 changes: 14 additions & 0 deletions tests/Fixtures/Role/ModelHasRole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;

use Illuminate\Database\Eloquent\Model;

class ModelHasRole extends Model
{
public $timestamps = false;

protected $table = 'model_has_roles';

protected $guarded = ['id'];
}
10 changes: 10 additions & 0 deletions tests/Fixtures/Role/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
protected $table = 'roles';
}
24 changes: 24 additions & 0 deletions tests/Fixtures/Role/RoleRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Fixtures\Role;

use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use Binaryk\LaravelRestify\Repositories\Repository;
use Binaryk\LaravelRestify\Tests\Fixtures\User\User;
use Illuminate\Database\Eloquent\Model;

class RoleRepository extends Repository
{
public static $model = Role::class;

public function attachUsers(RestifyRequest $request, Repository $repository, Model $model)
{
ModelHasRole::create([
'role_id' => $model->id,
'model_type' => User::class,
'model_id' => $request->get('users'),
]);

return $this->response()->created();
}
}
2 changes: 2 additions & 0 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -188,6 +189,7 @@ public function loadRepositories()
PostWithUnauthorizedFieldsRepository::class,
PostUnauthorizedFieldRepository::class,
PostWithHiddenFieldRepository::class,
RoleRepository::class,
]);
}

Expand Down
49 changes: 49 additions & 0 deletions tests/Migrations/2019_12_22_000006_create_roles_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->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');
}
}

0 comments on commit 0a892da

Please sign in to comment.