Add organizer invitation system: invite, accept, refuse

- OrganizerInvitation entity: companyName, firstName, lastName, email,
  message, status (sent/opened/accepted/refused), unique token (64 hex chars)
- Admin route /admin/organisateurs/inviter: form + invitation list with status
- Button "Inviter un organisateur" on admin organizers page
- Email with accept/refuse links using unique token
- Public route /invitation/{token}/{action}: accept or refuse without auth
- Response page: confirmation message for accept/refuse
- Migration, PHPStan config, 7 entity tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-22 17:41:31 +01:00
parent 233f3d5067
commit cca5575274
11 changed files with 531 additions and 4 deletions

View File

@@ -0,0 +1,85 @@
<?php
namespace App\Tests\Entity;
use App\Entity\OrganizerInvitation;
use PHPUnit\Framework\TestCase;
class OrganizerInvitationTest extends TestCase
{
public function testDefaults(): void
{
$inv = new OrganizerInvitation();
self::assertNull($inv->getId());
self::assertNull($inv->getCompanyName());
self::assertNull($inv->getFirstName());
self::assertNull($inv->getLastName());
self::assertNull($inv->getEmail());
self::assertNull($inv->getMessage());
self::assertSame(OrganizerInvitation::STATUS_SENT, $inv->getStatus());
self::assertSame(64, \strlen($inv->getToken()));
self::assertNull($inv->getRespondedAt());
self::assertInstanceOf(\DateTimeImmutable::class, $inv->getCreatedAt());
}
public function testSetAndGetCompanyName(): void
{
$inv = new OrganizerInvitation();
$result = $inv->setCompanyName('Asso Test');
self::assertSame('Asso Test', $inv->getCompanyName());
self::assertSame($inv, $result);
}
public function testSetAndGetNames(): void
{
$inv = new OrganizerInvitation();
$inv->setFirstName('Jean');
$inv->setLastName('Dupont');
$inv->setEmail('jean@test.fr');
self::assertSame('Jean', $inv->getFirstName());
self::assertSame('Dupont', $inv->getLastName());
self::assertSame('jean@test.fr', $inv->getEmail());
}
public function testSetAndGetMessage(): void
{
$inv = new OrganizerInvitation();
$result = $inv->setMessage('Bienvenue !');
self::assertSame('Bienvenue !', $inv->getMessage());
self::assertSame($inv, $result);
$inv->setMessage(null);
self::assertNull($inv->getMessage());
}
public function testSetAndGetStatus(): void
{
$inv = new OrganizerInvitation();
$result = $inv->setStatus(OrganizerInvitation::STATUS_ACCEPTED);
self::assertSame(OrganizerInvitation::STATUS_ACCEPTED, $inv->getStatus());
self::assertSame($inv, $result);
}
public function testSetAndGetRespondedAt(): void
{
$inv = new OrganizerInvitation();
$date = new \DateTimeImmutable();
$result = $inv->setRespondedAt($date);
self::assertSame($date, $inv->getRespondedAt());
self::assertSame($inv, $result);
}
public function testUniqueTokens(): void
{
$inv1 = new OrganizerInvitation();
$inv2 = new OrganizerInvitation();
self::assertNotSame($inv1->getToken(), $inv2->getToken());
}
}