Skip to content

Commit

Permalink
Add option to include soft deleted models
Browse files Browse the repository at this point in the history
  • Loading branch information
korridor committed Feb 28, 2024
1 parent 32fab9d commit 49370c7
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/Rules/ExistsEloquent.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class ExistsEloquent implements ValidationRule
*/
private ?string $customMessageTranslationKey = null;

/**
* Include soft deleted models in the query.
*
* @var bool
*/
private bool $includeSoftDeleted = false;

/**
* Create a new rule instance.
*
Expand Down Expand Up @@ -110,6 +117,10 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
$builder = $builderClosure($builder);
}

if ($this->includeSoftDeleted) {
$builder = $builder->withTrashed();
}

if ($builder->doesntExist()) {
if ($this->customMessage !== null) {
$fail($this->customMessage);
Expand Down Expand Up @@ -141,4 +152,26 @@ public function query(Closure $builderClosure): self

return $this;
}

/**
* Activate or deactivate including soft deleted models in the query.
*
* @param bool $includeSoftDeleted
* @return void
*/
public function setIncludeSoftDeleted(bool $includeSoftDeleted): void
{
$this->includeSoftDeleted = $includeSoftDeleted;
}

/**
* Activate including soft deleted models in the query.
* @return $this
*/
public function includeSoftDeleted(): self
{
$this->setIncludeSoftDeleted(true);

return $this;
}
}
34 changes: 34 additions & 0 deletions src/Rules/UniqueEloquent.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ class UniqueEloquent implements ValidationRule
*/
private ?string $customMessageTranslationKey = null;

/**
* Include soft deleted models in the query.
*
* @var bool
*/
private bool $includeSoftDeleted = false;

/**
* UniqueEloquent constructor.
*
Expand Down Expand Up @@ -97,6 +104,10 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
);
}

if ($this->includeSoftDeleted) {
$builder = $builder->withTrashed();
}

if ($builder->exists()) {
if ($this->customMessage !== null) {
$fail($this->customMessage);
Expand Down Expand Up @@ -178,4 +189,27 @@ public function ignore(mixed $id, ?string $column = null): self

return $this;
}

/**
* Activate or deactivate including soft deleted models in the query.
*
* @param bool $includeSoftDeleted
* @return void
*/
public function setIncludeSoftDeleted(bool $includeSoftDeleted): void
{
$this->includeSoftDeleted = $includeSoftDeleted;
}

/**
* Activate including soft deleted models in the query.
*
* @return $this
*/
public function includeSoftDeleted(): self
{
$this->setIncludeSoftDeleted(true);

return $this;
}
}
73 changes: 73 additions & 0 deletions tests/Feature/ExistsEloquentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,79 @@ public function testValidationPassesIfRuleChecksThatFactExistsAndBelongsToUserUs
$this->assertCount(1, Fact::all());
}

/*
* Tests for includeSoftDeleted
*/

public function testValidationSucceedsIfSoftDeletedEntryExistInDatabaseAndIncludeSoftDeletedFlagIsActive(): void
{
// Arrange
User::create([
'id' => 6,
'other_id' => null,
'name' => 'Testname',
'email' => '[email protected]',
'password' => bcrypt('secret'),
'remember_token' => Str::random(10),
]);
$fact = Fact::create([
'id' => 1,
'user_id' => 6,
'type' => 'type1',
'description' => 'Long desc',
]);
$fact->delete();

$validator = Validator::make([
'id' => 1,
], [
'id' => [(new ExistsEloquent(Fact::class))->includeSoftDeleted()]
]);

// Act
$isValid = $validator->passes();
$messages = $validator->messages()->toArray();

// Assert
$this->assertTrue($isValid);
$this->assertArrayNotHasKey('id', $messages);
$this->assertCount(1, User::withTrashed()->get());
$this->assertCount(1, User::all());
$this->assertCount(1, Fact::withTrashed()->get());
$this->assertCount(0, Fact::all());
}

public function testValidationFailsIfSoftDeletedEntryDoesNotExistInDatabaseAndIncludeSoftDeletedFlagIsActive(): void
{
// Arrange
User::create([
'id' => 6,
'other_id' => null,
'name' => 'Testname',
'email' => '[email protected]',
'password' => bcrypt('secret'),
'remember_token' => Str::random(10),
]);

$validator = Validator::make([
'id' => 1,
], [
'id' => [(new ExistsEloquent(Fact::class))->includeSoftDeleted()]
]);

// Act
$isValid = $validator->passes();
$messages = $validator->messages()->toArray();

// Assert
$this->assertFalse($isValid);
$this->assertEquals('The resource does not exist.', $messages['id'][0]);
$this->assertCount(1, User::withTrashed()->get());
$this->assertCount(1, User::all());
$this->assertCount(0, Fact::withTrashed()->get());
$this->assertCount(0, Fact::all());
}

/*
* Test language support
*/
Expand Down
73 changes: 73 additions & 0 deletions tests/Feature/UniqueEloquentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,79 @@ public function testValidationFailsIfRuleChecksThatFactExistsAndBelongsToUserUsi
$this->assertCount(1, Fact::all());
}

/*
* Tests for includeSoftDeleted
*/

public function testValidationSucceedsIfSoftDeletedEntryDoesNotExistInDatabaseAndIncludeSoftDeletedFlagIsActive(): void
{
// Arrange
User::create([
'id' => 6,
'other_id' => null,
'name' => 'Testname',
'email' => '[email protected]',
'password' => bcrypt('secret'),
'remember_token' => Str::random(10),
]);

$validator = Validator::make([
'id' => 1,
], [
'id' => [(new UniqueEloquent(Fact::class))->includeSoftDeleted()]
]);

// Act
$isValid = $validator->passes();
$messages = $validator->messages()->toArray();

// Assert
$this->assertTrue($isValid);
$this->assertArrayNotHasKey('id', $messages);
$this->assertCount(1, User::withTrashed()->get());
$this->assertCount(1, User::all());
$this->assertCount(0, Fact::withTrashed()->get());
$this->assertCount(0, Fact::all());
}

public function testValidationFailsIfSoftDeletedEntryDoesExistInDatabaseAndIncludeSoftDeletedFlagIsActive(): void
{
// Arrange
User::create([
'id' => 6,
'other_id' => null,
'name' => 'Testname',
'email' => '[email protected]',
'password' => bcrypt('secret'),
'remember_token' => Str::random(10),
]);
$fact = Fact::create([
'id' => 1,
'user_id' => 6,
'type' => 'type1',
'description' => 'Long desc',
]);
$fact->delete();

$validator = Validator::make([
'id' => 1,
], [
'id' => [(new UniqueEloquent(Fact::class))->includeSoftDeleted()]
]);

// Act
$isValid = $validator->passes();
$messages = $validator->messages()->toArray();

// Assert
$this->assertFalse($isValid);
$this->assertEquals('The resource already exists.', $messages['id'][0]);
$this->assertCount(1, User::withTrashed()->get());
$this->assertCount(1, User::all());
$this->assertCount(1, Fact::withTrashed()->get());
$this->assertCount(0, Fact::all());
}

/*
* Test language support
*/
Expand Down

0 comments on commit 49370c7

Please sign in to comment.