- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD) * DEV: Clés TEST Pierre (mode test) * REC: Clés TEST Client (mode test) * PROD: Clés LIVE Client (mode live) - Ajout de la gestion des bases de données immeubles/bâtiments * Configuration buildings_database pour DEV/REC/PROD * Service BuildingService pour enrichissement des adresses - Optimisations pages et améliorations ergonomie - Mises à jour des dépendances Composer - Nettoyage des fichiers obsolètes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
177 lines
5.2 KiB
PHP
177 lines
5.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Classe abstraite de base pour tous les migrators
|
|
*
|
|
* Fournit les méthodes communes pour migrer des données d'une table
|
|
*/
|
|
abstract class DataMigrator
|
|
{
|
|
protected $connection;
|
|
protected $logger;
|
|
protected $sourceDb;
|
|
protected $targetDb;
|
|
|
|
/**
|
|
* Constructeur
|
|
*
|
|
* @param DatabaseConnection $connection Connexion aux bases
|
|
* @param MigrationLogger $logger Logger
|
|
*/
|
|
public function __construct(DatabaseConnection $connection, MigrationLogger $logger)
|
|
{
|
|
$this->connection = $connection;
|
|
$this->logger = $logger;
|
|
$this->sourceDb = $connection->getSourceDb();
|
|
$this->targetDb = $connection->getTargetDb();
|
|
}
|
|
|
|
/**
|
|
* Méthode principale de migration (à implémenter dans chaque migrator)
|
|
*
|
|
* @param int|null $entityId ID de l'entité à migrer (null = toutes)
|
|
* @param bool $deleteBefore Supprimer les données existantes avant migration
|
|
* @return array ['success' => int, 'errors' => int]
|
|
*/
|
|
abstract public function migrate(?int $entityId = null, bool $deleteBefore = false): array;
|
|
|
|
/**
|
|
* Retourne le nom de la table gérée par ce migrator
|
|
*/
|
|
abstract public function getTableName(): string;
|
|
|
|
/**
|
|
* Supprime les données d'une entité dans la cible
|
|
* À surcharger si la logique de suppression est spécifique
|
|
*
|
|
* @param int $entityId ID de l'entité
|
|
* @return int Nombre de lignes supprimées
|
|
*/
|
|
protected function deleteEntityData(int $entityId): int
|
|
{
|
|
$table = $this->getTableName();
|
|
|
|
try {
|
|
// Par défaut: suppression simple avec fk_entite
|
|
$stmt = $this->targetDb->prepare("DELETE FROM $table WHERE fk_entite = ?");
|
|
$stmt->execute([$entityId]);
|
|
$deleted = $stmt->rowCount();
|
|
|
|
if ($deleted > 0) {
|
|
$this->logger->debug(" Supprimé $deleted ligne(s) de $table pour entité #$entityId");
|
|
}
|
|
|
|
return $deleted;
|
|
|
|
} catch (PDOException $e) {
|
|
$this->logger->warning(" Erreur suppression $table: " . $e->getMessage());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compte les lignes dans la source
|
|
*
|
|
* @param int|null $entityId ID de l'entité (null = toutes)
|
|
* @return int Nombre de lignes
|
|
*/
|
|
protected function countSourceRows(?int $entityId = null): int
|
|
{
|
|
return $this->connection->countSourceRows($this->getTableName(), $entityId);
|
|
}
|
|
|
|
/**
|
|
* Compte les lignes dans la cible
|
|
*
|
|
* @param int|null $entityId ID de l'entité (null = toutes)
|
|
* @return int Nombre de lignes
|
|
*/
|
|
protected function countTargetRows(?int $entityId = null): int
|
|
{
|
|
return $this->connection->countTargetRows($this->getTableName(), $entityId);
|
|
}
|
|
|
|
/**
|
|
* Log le début de la migration d'une table
|
|
*/
|
|
protected function logStart(?int $entityId = null): void
|
|
{
|
|
$table = $this->getTableName();
|
|
$entityStr = $entityId ? " pour entité #$entityId" : " (toutes les entités)";
|
|
$this->logger->info("🔄 Migration de $table{$entityStr}...");
|
|
}
|
|
|
|
/**
|
|
* Log la fin de la migration avec statistiques
|
|
*
|
|
* @param int $success Nombre de succès
|
|
* @param int $errors Nombre d'erreurs
|
|
* @param int|null $entityId ID de l'entité
|
|
*/
|
|
protected function logEnd(int $success, int $errors, ?int $entityId = null): void
|
|
{
|
|
$table = $this->getTableName();
|
|
$sourceCount = $this->countSourceRows($entityId);
|
|
$targetCount = $this->countTargetRows($entityId);
|
|
$diff = $targetCount - $sourceCount;
|
|
$diffStr = $diff >= 0 ? "+$diff" : "$diff";
|
|
|
|
if ($errors > 0) {
|
|
$this->logger->warning(" ⚠️ $table: $success succès, $errors erreurs");
|
|
} else {
|
|
$this->logger->success(" ✓ $table: $success enregistrement(s) migré(s)");
|
|
}
|
|
|
|
$this->logger->info(" 📊 SOURCE: $sourceCount → CIBLE: $targetCount (différence: $diffStr)");
|
|
}
|
|
|
|
/**
|
|
* Exécute une requête INSERT avec ON DUPLICATE KEY UPDATE
|
|
*
|
|
* @param string $insertSql SQL d'insertion
|
|
* @param array $data Données à insérer
|
|
* @return bool True si succès
|
|
*/
|
|
protected function insertOrUpdate(string $insertSql, array $data): bool
|
|
{
|
|
try {
|
|
$stmt = $this->targetDb->prepare($insertSql);
|
|
$stmt->execute($data);
|
|
return true;
|
|
} catch (PDOException $e) {
|
|
$this->logger->debug(" Erreur INSERT: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Démarre une transaction sur la cible
|
|
*/
|
|
protected function beginTransaction(): void
|
|
{
|
|
if (!$this->targetDb->inTransaction()) {
|
|
$this->targetDb->beginTransaction();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Commit la transaction
|
|
*/
|
|
protected function commit(): void
|
|
{
|
|
if ($this->targetDb->inTransaction()) {
|
|
$this->targetDb->commit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Rollback la transaction
|
|
*/
|
|
protected function rollback(): void
|
|
{
|
|
if ($this->targetDb->inTransaction()) {
|
|
$this->targetDb->rollBack();
|
|
}
|
|
}
|
|
}
|