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(); } } }