Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Binaryk\LaravelRestify\Http\Controllers\GlobalSearchController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryAttachController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryDestroyController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryDetachController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryFilterController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryIndexController;
use Binaryk\LaravelRestify\Http\Controllers\RepositoryShowController;
Expand All @@ -26,3 +27,4 @@

// Attach related repository id
Route::post('/{repository}/{repositoryId}/attach/{relatedRepository}', '\\'.RepositoryAttachController::class);
Route::post('/{repository}/{repositoryId}/detach/{relatedRepository}', '\\'.RepositoryDetachController::class);
64 changes: 64 additions & 0 deletions src/Http/Controllers/RepositoryDetachController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Binaryk\LaravelRestify\Http\Controllers;

use Binaryk\LaravelRestify\Http\Requests\RepositoryDetachRequest;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use DateTime;
use Illuminate\Support\Arr;

class RepositoryDetachController extends RepositoryController
{
public function __invoke(RepositoryDetachRequest $request)
{
$model = $request->findModelOrFail();
$repository = $request->repository()->allowToUpdate($request);

return $repository->detach(
$request, $request->repositoryId,
collect(Arr::wrap($request->input($request->relatedRepository)))
->map(fn ($relatedRepositoryId) => $this->initializePivot(
$request, $model->{$request->viaRelationship ?? $request->relatedRepository}(), $relatedRepositoryId
))
);
}

/**
* Initialize a fresh pivot model for the relationship.
*
* @param RestifyRequest $request
* @param $relationship
* @return mixed
* @throws \Binaryk\LaravelRestify\Exceptions\Eloquent\EntityNotFoundException
* @throws \Binaryk\LaravelRestify\Exceptions\UnauthorizedException
*/
protected function initializePivot(RestifyRequest $request, $relationship, $relatedKey)
{
$parentKey = $request->repositoryId;

$parentKeyName = $relationship->getParentKeyName();
$relatedKeyName = $relationship->getRelatedKeyName();

if ($parentKeyName !== $request->model()->getKeyName()) {
$parentKey = $request->findModelOrFail()->{$parentKeyName};
}

if ($relatedKeyName !== ($request->newRelatedRepository()::newModel())->getKeyName()) {
$relatedKey = $request->findRelatedModelOrFail()->{$relatedKeyName};
}

($pivot = $relationship->newPivot())->forceFill([
$relationship->getForeignPivotKeyName() => $parentKey,
$relationship->getRelatedPivotKeyName() => $relatedKey,
]);

if ($relationship->withTimestamps) {
$pivot->forceFill([
$relationship->createdAt() => new DateTime,
$relationship->updatedAt() => new DateTime,
]);
}

return $pivot;
}
}
7 changes: 7 additions & 0 deletions src/Http/Requests/RepositoryDetachRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Binaryk\LaravelRestify\Http\Requests;

class RepositoryDetachRequest extends RestifyRequest
{
}
11 changes: 11 additions & 0 deletions src/Repositories/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,17 @@ public function attach(RestifyRequest $request, $repositoryId, Collection $pivot
->created();
}

public function detach(RestifyRequest $request, $repositoryId, Collection $pivots)
{
$deleted = DB::transaction(function () use ($request, $pivots) {
return $pivots->map(fn ($pivot) => $pivot->delete());
});

return $this->response()
->data($deleted)
->deleted();
}

public function destroy(RestifyRequest $request, $repositoryId)
{
$status = DB::transaction(function () {
Expand Down
66 changes: 66 additions & 0 deletions tests/Controllers/RepositoryAttachControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Controllers;

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

class RepositoryAttachControllerTest extends IntegrationTest
{
public function test_attach_a_user_to_a_company()
{
$user = $this->mockUsers(2)->first();
$company = factory(Company::class)->create();

$response = $this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
'users' => $user->id,
'is_admin' => true,
])
->assertStatus(201);

$response->assertJsonFragment([
'company_id' => '1',
'user_id' => $user->id,
'is_admin' => true,
]);
}

public function test_attach_multiple_users_to_a_company()
{
$user = $this->mockUsers(2)->first();
$company = factory(Company::class)->create();
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(0, $usersFromCompany->json('data'));

$response = $this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
'users' => [1, 2],
'is_admin' => true,
])
->assertStatus(201);

$response->assertJsonFragment([
'company_id' => '1',
'user_id' => $user->id,
'is_admin' => true,
]);

$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(2, $usersFromCompany->json('data'));
}

public function test_after_attach_a_user_to_company_number_of_users_increased()
{
$user = $this->mockUsers()->first();
$company = factory(Company::class)->create();

$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(0, $usersFromCompany->json('data'));

$this->postJson('restify-api/companies/'.$company->id.'/attach/users', [
'users' => $user->id,
]);

$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(1, $usersFromCompany->json('data'));
}
}
42 changes: 42 additions & 0 deletions tests/Controllers/RepositoryDetachControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Controllers;

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

class RepositoryDetachControllerTest extends IntegrationTest
{
public function test_detach_a_user_from_a_company()
{
$user = $this->mockUsers(2)->first();
$company = factory(Company::class)->create();
$company->users()->attach($user->id);
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(1, $usersFromCompany->json('data'));
$this->postJson('restify-api/companies/'.$company->id.'/detach/users', [
'users' => $user->id,
])
->assertStatus(204);
$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(0, $usersFromCompany->json('data'));
}

public function test_detach_multiple_users_from_a_company()
{
$users = $this->mockUsers(3);
$company = factory(Company::class)->create();
$company->users()->attach($users->pluck('id'));

$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(3, $usersFromCompany->json('data'));

$this->postJson('restify-api/companies/'.$company->id.'/detach/users', [
'users' => [1, 2],
])
->assertStatus(204);

$usersFromCompany = $this->getJson('/restify-api/users?viaRepository=companies&viaRepositoryId=1&viaRelationship=users');
$this->assertCount(1, $usersFromCompany->json('data'));
}
}