feat: soft-delete for teamer accounts

addresses #869dv9br3
This commit is contained in:
Björn Fromme
2026-08-11 12:26:13 +02:00
parent 388ecf9603
commit d654ce77fb
45 changed files with 1151 additions and 7 deletions
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace App\Tests\Entity\Traits;
use App\Entity\SoftDeletableEntityInterface;
use App\Entity\Traits\SoftDeletableEntity;
use PHPUnit\Framework\TestCase;
class SoftDeletableEntityTest extends TestCase
{
public function testAFreshEntityIsNotDeleted(): void
{
$entity = $this->createEntity();
$this->assertFalse($entity->isDeleted());
$this->assertNull($entity->getDeletedAt());
}
public function testSetDeletedStampsTheTimestamp(): void
{
$entity = $this->createEntity();
$entity->setDeleted();
$this->assertTrue($entity->isDeleted());
$this->assertNotNull($entity->getDeletedAt());
}
public function testSetRestoredClearsTheTimestamp(): void
{
$entity = $this->createEntity();
$entity->setDeleted();
$entity->setRestored();
$this->assertFalse($entity->isDeleted());
$this->assertNull($entity->getDeletedAt());
}
public function testDeletedAtAcceptsNullSoDeletionsCanBeUndone(): void
{
$entity = $this->createEntity();
$entity->setDeletedAt(new \DateTimeImmutable());
$entity->setDeletedAt(null);
$this->assertFalse($entity->isDeleted());
}
private function createEntity(): SoftDeletableEntityInterface
{
return new class implements SoftDeletableEntityInterface {
use SoftDeletableEntity;
};
}
}
+39
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Tests\Entity;
use App\Entity\Teamer;
use App\Entity\User;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\ConstraintViolationListInterface;
@@ -118,6 +119,44 @@ class UserTest extends TestCase
$this->assertNull($enabled->getDisabledAt());
}
/**
* A block and a deletion are independent states: setting one must never imply or
* clear the other, so that a disciplinary block survives a deletion and the restore
* that follows it.
*/
public function testDeletionAndBlockAreIndependentStates(): void
{
$user = new User();
$this->assertFalse($user->isBlocked());
$user->setDeleted();
$this->assertTrue($user->isBlocked());
$this->assertFalse($user->isDisabled());
$user->setDisabled(true);
$disabledAt = $user->getDisabledAt();
$user->setRestored();
$this->assertFalse($user->isDeleted());
$this->assertTrue($user->isBlocked());
$this->assertSame($disabledAt, $user->getDisabledAt());
$user->setDisabled(false);
$this->assertFalse($user->isBlocked());
}
public function testSettingTheTeamerKeepsTheInverseSideInSync(): void
{
$teamer = new Teamer();
$user = (new User())->setTeamer($teamer);
$this->assertSame($user, $teamer->getUser());
$user->setTeamer(null);
$this->assertNull($teamer->getUser());
}
private function validate(User $user): ConstraintViolationListInterface
{
return Validation::createValidatorBuilder()