# Infrastructure

## C'est quoi l'Infrastructure ?

C'est la couche qui fait le "vrai travail technique". Elle sait parler à MySQL, générer un JWT, envoyer un email, uploader un fichier, appeler Stripe.

Le reste du code (Domain, Application) ne sait pas comment ces choses fonctionnent — il passe par des interfaces. L'Infrastructure, elle, implémente ces interfaces concrètement.

> Si demain tu changes MySQL pour PostgreSQL, ou Stripe pour PayPlug — tu modifies uniquement l'Infrastructure. Le reste du code ne bouge pas.

---

## Structure

```
Infrastructure/
├── Auth/          → Authentification (JWT, OAuth, 2FA)
├── Export/        → Génération de fichiers (PDF, Word)
├── Listener/      → Écouteurs d'événements Symfony
├── Notification/  → Envoi d'emails et notifications
├── Payment/       → Gestion des paiements (Stripe...)
├── Persistence/   → Accès à la base de données (Doctrine)
│   └── Doctrine/
│       ├── Entity/     → Mapping Doctrine des tables SQL
│       ├── Mapper/     → Conversion Entity ↔ Domain
│       ├── Migration/  → Migrations de base de données
│       └── Repository/ → Implémentations des repositories
└── Storage/       → Upload et stockage de fichiers
```

---

## `Auth/`

**Rôle** : tout ce qui concerne l'authentification technique.

**Pourquoi** : l'Application sait qu'elle doit "générer un token" ou "connecter un utilisateur via OAuth" — mais elle ne sait pas comment. C'est l'Infrastructure qui implémente ça concrètement.

### `Auth/` — Fichiers existants

| Fichier | Rôle |
|---|---|
| `JwtService.php` | Implémente `JwtServiceInterface` — génère un token JWT via LexikJWTAuthenticationBundle |
| `SymfonyUser.php` | Pont entre l'entité `User` Domain et `UserInterface` Symfony — nécessaire pour que Lexik JWT reconnaisse l'utilisateur |

### `Auth/` — À créer

| Fichier | Rôle |
|---|---|
| `OAuth/GoogleOAuthService.php` | Connexion via Google |
| `OAuth/FacebookOAuthService.php` | Connexion via Facebook |
| `OAuth/LinkedInOAuthService.php` | Connexion via LinkedIn |
| `Security/AppAuthenticator.php` | Guard Symfony pour les firewalls |
| `TwoFactor/TwoFactorService.php` | Gestion du 2FA pour le back-office superadmin |

---

## `Persistence/`

**Rôle** : tout ce qui concerne l'accès à la base de données.

**Pourquoi** : le Domain et l'Application ne connaissent pas Doctrine. Ils passent par des interfaces (`UserRepositoryInterface`). C'est ici qu'on implémente ces interfaces concrètement avec Doctrine.

### `Persistence/Doctrine/Entity/`

**Rôle** : classes de mapping Doctrine — elles représentent les tables SQL et leurs colonnes.

**Important** : ces entités ne sont pas les entités Domain. Ce sont des objets techniques qui servent uniquement à Doctrine pour lire et écrire en base. On les convertit ensuite en objets Domain via les Mappers.

| Fichier | Table SQL |
|---|---|
| `UserEntity.php` | `gp_Utilisateurs` |

**À créer :**

| Fichier | Table SQL |
|---|---|
| `ProjectEntity.php` | `gp_Projets` |
| `ModuleEntity.php` | `gp_Modules` |
| `SubscriptionEntity.php` | `gp_Abonnements` |
| `HistoryEntity.php` | `gp_Historique` |

### `Persistence/Doctrine/Mapper/`

**Rôle** : convertit une `Entity` Doctrine en objet `Domain` et inversement.

**Pourquoi** : Doctrine a besoin de ses propres objets pour fonctionner. Le Domain a ses propres objets. Le Mapper fait le pont entre les deux.

```
UserEntity (Doctrine)  ←→  UserMapper  ←→  User (Domain)
```

| Fichier | Rôle |
|---|---|
| `UserMapper.php` | Convertit `UserEntity` ↔ `User` Domain |

**À créer :**

| Fichier | Rôle |
|---|---|
| `ProjectMapper.php` | Convertit `ProjectEntity` ↔ `Project` Domain |
| `ModuleMapper.php` | Convertit `ModuleEntity` ↔ `Module` Domain |
| `SubscriptionMapper.php` | Convertit `SubscriptionEntity` ↔ `Subscription` Domain |

### `Persistence/Doctrine/Repository/`

**Rôle** : implémentations concrètes des interfaces de repository définies dans `Application/Port/Repository/`.

**Comment on l'utilise** : on n'appelle jamais directement ces classes. On passe toujours par l'interface. C'est `config/services.yaml` qui fait le lien.

| Fichier | Interface implémentée |
|---|---|
| `DoctrineUserRepository.php` | `UserRepositoryInterface` |

**À créer :**

| Fichier | Interface implémentée |
|---|---|
| `DoctrineProjectRepository.php` | `ProjectRepositoryInterface` |
| `DoctrineModuleRepository.php` | `ModuleRepositoryInterface` |
| `DoctrineSubscriptionRepository.php` | `SubscriptionRepositoryInterface` |

### `Persistence/Doctrine/Migration/`

**Rôle** : historique des modifications du schéma de base de données. Chaque migration correspond à une modification de structure SQL.

---

## `Notification/`

**Rôle** : envoi d'emails et autres notifications.

**À créer :**

| Fichier | Interface implémentée |
|---|---|
| `MailService.php` | `MailServiceInterface` |

---

## `Export/`

**Rôle** : génération de fichiers exportables à partir d'un projet.

**À créer :**

| Fichier | Interface implémentée |
|---|---|
| `PdfExportService.php` | `ExportServiceInterface` |
| `WordExportService.php` | `ExportServiceInterface` |

---

## `Payment/`

**Rôle** : gestion des paiements et abonnements via Stripe.

**À créer :**

| Fichier | Interface implémentée |
|---|---|
| `StripePaymentService.php` | `PaymentServiceInterface` |

---

## `Storage/`

**Rôle** : upload et récupération de fichiers (avatars, pièces jointes...).

**À créer :**

| Fichier | Interface implémentée |
|---|---|
| `LocalStorageService.php` | `StorageServiceInterface` |

---

## `Listener/`

**Rôle** : écouteurs d'événements Symfony et Domain.

**Pourquoi** : quand un événement est émis (ex: `UserRegisteredEvent`), un Listener peut réagir — envoyer un email de bienvenue, créer un log, notifier un admin — sans que le Use Case le sache.

**À créer :**

| Fichier | Rôle |
|---|---|
| `SendWelcomeEmailListener.php` | Envoie un email de bienvenue à l'inscription |
| `LogUserActionListener.php` | Enregistre les actions importantes en base |

---

## Règles à respecter

- Chaque classe ici implémente une interface définie dans `Application/Port/`
- On déclare le lien interface → implémentation dans `config/services.yaml`
- Les Entities Doctrine ne sortent jamais de l'Infrastructure — on les convertit toujours en objets Domain via les Mappers
- On n'appelle jamais directement un Repository concret — toujours via son interface