refactor(core) : isole Core du module Sites via SiteProviderInterface + resolve_target_entities
Supprime les imports directs de App\Module\Sites\* depuis le module Core : - SiteProviderInterface (Shared/Contract) : contrat minimal findByName(), etendu par SiteRepositoryInterface pour reutilisation DI. - AppFixtures : injecte SiteProviderInterface au lieu de SiteRepositoryInterface. - User.php : targetEntity des mappings ORM pointe desormais sur SiteInterface, resolu a la classe concrete via doctrine.orm.resolve_target_entities (pattern officiel Doctrine pour les bounded contexts DDD). - JoinColumn/InverseJoinColumn explicites sur la ManyToMany user_site pour forcer les noms de colonnes (sinon Doctrine derive site_interface_id). Respecte la regle CLAUDE.md "jamais d'import direct entre modules" — il reste l'exception SitesFixtures::class dans getDependencies() (contrainte d'API DependentFixtureInterface, meme registre que resolve_target_entities). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,12 +15,11 @@ use App\Module\Core\Infrastructure\ApiPlatform\State\Processor\UserProcessor;
|
||||
use App\Module\Core\Infrastructure\ApiPlatform\State\Processor\UserRbacProcessor;
|
||||
use App\Module\Core\Infrastructure\ApiPlatform\State\Provider\MeProvider;
|
||||
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
|
||||
// Note architecture : User.php utilise SiteInterface (Shared) pour les
|
||||
// type-hints afin de ne pas coupler le module Core au module Sites.
|
||||
// La seule reference concrete a Site subsiste dans les metadonnees ORM
|
||||
// (targetEntity) via FQCN string, ce qui est obligatoire pour Doctrine.
|
||||
// SiteNotAuthorizedException est importee depuis Shared (sa location canonique).
|
||||
use App\Module\Sites\Domain\Entity\Site;
|
||||
// Note architecture : User.php n'importe plus rien depuis le module Sites.
|
||||
// Les type-hints utilisent SiteInterface (Shared/Contract) et le mapping ORM
|
||||
// pointe vers la meme interface, resolue vers la classe concrete Site au boot
|
||||
// via `doctrine.orm.resolve_target_entities` (cf. config/packages/doctrine.yaml).
|
||||
// C'est le pattern officiel Doctrine pour les bounded contexts DDD.
|
||||
use App\Shared\Domain\Attribute\Auditable;
|
||||
use App\Shared\Domain\Attribute\AuditIgnore;
|
||||
use App\Shared\Domain\Contract\SiteInterface;
|
||||
@@ -139,10 +138,12 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
* Le groupe `user:list` a ete retire deliberement (securite : evite
|
||||
* de fuiter la liste des sites de chaque user via GET /api/users).
|
||||
*
|
||||
* @var Collection<int, Site>
|
||||
* @var Collection<int, SiteInterface>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: 'App\Module\Sites\Domain\Entity\Site', inversedBy: 'users', fetch: 'LAZY')]
|
||||
#[ORM\ManyToMany(targetEntity: SiteInterface::class, inversedBy: 'users', fetch: 'LAZY')]
|
||||
#[ORM\JoinTable(name: 'user_site')]
|
||||
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
#[ORM\InverseJoinColumn(name: 'site_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
#[Groups(['me:read', 'user:rbac:read', 'user:rbac:write'])]
|
||||
private Collection $sites;
|
||||
|
||||
@@ -162,7 +163,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
* le prechargement pour /api/me. Le groupe `user:list` a ete retire
|
||||
* deliberement (securite : evite de fuiter le site actif via /api/users).
|
||||
*/
|
||||
#[ORM\ManyToOne(targetEntity: 'App\Module\Sites\Domain\Entity\Site', fetch: 'LAZY')]
|
||||
#[ORM\ManyToOne(targetEntity: SiteInterface::class, fetch: 'LAZY')]
|
||||
#[ORM\JoinColumn(name: 'current_site_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
#[Groups(['me:read'])]
|
||||
private ?SiteInterface $currentSite = null;
|
||||
@@ -378,7 +379,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Site>
|
||||
* @return Collection<int, SiteInterface>
|
||||
*/
|
||||
public function getSites(): Collection
|
||||
{
|
||||
@@ -392,7 +393,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
* session Doctrine (cf. ticket 2 review point #1).
|
||||
*
|
||||
* Le parametre est type SiteInterface pour eviter le couplage Core → Sites.
|
||||
* En pratique seule App\Module\Sites\Domain\Entity\Site est passee ici.
|
||||
* La classe concrete injectee au runtime est resolue par Doctrine via
|
||||
* `resolve_target_entities` (cf. note architecture en tete de fichier).
|
||||
*/
|
||||
public function addSite(SiteInterface $site): static
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user