Skip to content

Commit 5bf9fea

Browse files
authored
Related repositories (#184)
* Attach related repositories * Detach items * Apply fixes from StyleCI (#183)
1 parent a3118f4 commit 5bf9fea

File tree

6 files changed

+192
-0
lines changed

6 files changed

+192
-0
lines changed

routes/api.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use Binaryk\LaravelRestify\Http\Controllers\GlobalSearchController;
44
use Binaryk\LaravelRestify\Http\Controllers\RepositoryAttachController;
55
use Binaryk\LaravelRestify\Http\Controllers\RepositoryDestroyController;
6+
use Binaryk\LaravelRestify\Http\Controllers\RepositoryDetachController;
67
use Binaryk\LaravelRestify\Http\Controllers\RepositoryFilterController;
78
use Binaryk\LaravelRestify\Http\Controllers\RepositoryIndexController;
89
use Binaryk\LaravelRestify\Http\Controllers\RepositoryShowController;
@@ -26,3 +27,4 @@
2627

2728
// Attach related repository id
2829
Route::post('/{repository}/{repositoryId}/attach/{relatedRepository}', '\\'.RepositoryAttachController::class);
30+
Route::post('/{repository}/{repositoryId}/detach/{relatedRepository}', '\\'.RepositoryDetachController::class);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Http\Controllers;
4+
5+
use Binaryk\LaravelRestify\Http\Requests\RepositoryDetachRequest;
6+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
7+
use DateTime;
8+
use Illuminate\Support\Arr;
9+
10+
class RepositoryDetachController extends RepositoryController
11+
{
12+
public function __invoke(RepositoryDetachRequest $request)
13+
{
14+
$model = $request->findModelOrFail();
15+
$repository = $request->repository()->allowToUpdate($request);
16+
17+
return $repository->detach(
18+
$request, $request->repositoryId,
19+
collect(Arr::wrap($request->input($request->relatedRepository)))
20+
->map(fn ($relatedRepositoryId) => $this->initializePivot(
21+
$request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId
22+
))
23+
);
24+
}
25+
26+
/**
27+
* Initialize a fresh pivot model for the relationship.
28+
*
29+
* @param RestifyRequest $request
30+
* @param $relationship
31+
* @return mixed
32+
* @throws \Binaryk\LaravelRestify\Exceptions\Eloquent\EntityNotFoundException
33+
* @throws \Binaryk\LaravelRestify\Exceptions\UnauthorizedException
34+
*/
35+
protected function initializePivot(RestifyRequest $request, $relationship, $relatedKey)
36+
{
37+
$parentKey = $request->repositoryId;
38+
39+
$parentKeyName = $relationship->getParentKeyName();
40+
$relatedKeyName = $relationship->getRelatedKeyName();
41+
42+
if ($parentKeyName !== $request->model()->getKeyName()) {
43+
$parentKey = $request->findModelOrFail()->{$parentKeyName};
44+
}
45+
46+
if ($relatedKeyName !== ($request->newRelatedRepository()::newModel())->getKeyName()) {
47+
$relatedKey = $request->findRelatedModelOrFail()->{$relatedKeyName};
48+
}
49+
50+
($pivot = $relationship->newPivot())->forceFill([
51+
$relationship->getForeignPivotKeyName() => $parentKey,
52+
$relationship->getRelatedPivotKeyName() => $relatedKey,
53+
]);
54+
55+
if ($relationship->withTimestamps) {
56+
$pivot->forceFill([
57+
$relationship->createdAt() => new DateTime,
58+
$relationship->updatedAt() => new DateTime,
59+
]);
60+
}
61+
62+
return $pivot;
63+
}
64+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Http\Requests;
4+
5+
class RepositoryDetachRequest extends RestifyRequest
6+
{
7+
}

src/Repositories/Repository.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,17 @@ public function attach(RestifyRequest $request, $repositoryId, Collection $pivot
586586
->created();
587587
}
588588

589+
public function detach(RestifyRequest $request, $repositoryId, Collection $pivots)
590+
{
591+
$deleted = DB::transaction(function () use ($request, $pivots) {
592+
return $pivots->map(fn ($pivot) => $pivot->delete());
593+
});
594+
595+
return $this->response()
596+
->data($deleted)
597+
->deleted();
598+
}
599+
589600
public function destroy(RestifyRequest $request, $repositoryId)
590601
{
591602
$status = DB::transaction(function () {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Controllers;
4+
5+
use Binaryk\LaravelRestify\Tests\Fixtures\Company\Company;
6+
use Binaryk\LaravelRestify\Tests\IntegrationTest;
7+
8+
class RepositoryAttachControllerTest extends IntegrationTest
9+
{
10+
public function test_attach_a_user_to_a_company()
11+
{
12+
$user = $this->mockUsers(2)->first();
13+
$company = factory(Company::class)->create();
14+
15+
$response = $this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
16+
'users' => $user->id,
17+
'is_admin' => true,
18+
])
19+
->assertStatus(201);
20+
21+
$response->assertJsonFragment([
22+
'company_id' => '1',
23+
'user_id' => $user->id,
24+
'is_admin' => true,
25+
]);
26+
}
27+
28+
public function test_attach_multiple_users_to_a_company()
29+
{
30+
$user = $this->mockUsers(2)->first();
31+
$company = factory(Company::class)->create();
32+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
33+
$this->assertCount(0, $usersFromCompany->json('data'));
34+
35+
$response = $this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
36+
'users' => [1, 2],
37+
'is_admin' => true,
38+
])
39+
->assertStatus(201);
40+
41+
$response->assertJsonFragment([
42+
'company_id' => '1',
43+
'user_id' => $user->id,
44+
'is_admin' => true,
45+
]);
46+
47+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
48+
$this->assertCount(2, $usersFromCompany->json('data'));
49+
}
50+
51+
public function test_after_attach_a_user_to_company_number_of_users_increased()
52+
{
53+
$user = $this->mockUsers()->first();
54+
$company = factory(Company::class)->create();
55+
56+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
57+
$this->assertCount(0, $usersFromCompany->json('data'));
58+
59+
$this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
60+
'users' => $user->id,
61+
]);
62+
63+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
64+
$this->assertCount(1, $usersFromCompany->json('data'));
65+
}
66+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Controllers;
4+
5+
use Binaryk\LaravelRestify\Tests\Fixtures\Company\Company;
6+
use Binaryk\LaravelRestify\Tests\IntegrationTest;
7+
8+
class RepositoryDetachControllerTest extends IntegrationTest
9+
{
10+
public function test_detach_a_user_from_a_company()
11+
{
12+
$user = $this->mockUsers(2)->first();
13+
$company = factory(Company::class)->create();
14+
$company->users()->attach($user->id);
15+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
16+
$this->assertCount(1, $usersFromCompany->json('data'));
17+
$this->postJson('restify-api/companies/'.$company->id.'/detach/users', [
18+
'users' => $user->id,
19+
])
20+
->assertStatus(204);
21+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
22+
$this->assertCount(0, $usersFromCompany->json('data'));
23+
}
24+
25+
public function test_detach_multiple_users_from_a_company()
26+
{
27+
$users = $this->mockUsers(3);
28+
$company = factory(Company::class)->create();
29+
$company->users()->attach($users->pluck('id'));
30+
31+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
32+
$this->assertCount(3, $usersFromCompany->json('data'));
33+
34+
$this->postJson('restify-api/companies/'.$company->id.'/detach/users', [
35+
'users' => [1, 2],
36+
])
37+
->assertStatus(204);
38+
39+
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
40+
$this->assertCount(1, $usersFromCompany->json('data'));
41+
}
42+
}

0 commit comments

Comments
 (0)