diff options
| author | polo <ordipolo@gmx.fr> | 2026-06-30 22:05:06 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2026-06-30 22:05:06 +0200 |
| commit | 9021dc699874c46b72dcbe019ec1a4408fbf6d70 (patch) | |
| tree | 9fdb40800547ecd9843ebd57ee069a13bf84eeed | |
| parent | de2488b7a45f63e128a4f2f393e1040323837a62 (diff) | |
| download | cms-9021dc699874c46b72dcbe019ec1a4408fbf6d70.tar.gz cms-9021dc699874c46b72dcbe019ec1a4408fbf6d70.tar.bz2 cms-9021dc699874c46b72dcbe019ec1a4408fbf6d70.zip | |
restore_db.php n'exclue plus la table 'user', possibilité de restaurer une BDD vide ou incomplète
| -rw-r--r-- | src/controller/MaintenanceController.php | 4 | ||||
| -rw-r--r-- | src/service/Backup.php | 59 |
2 files changed, 37 insertions, 26 deletions
diff --git a/src/controller/MaintenanceController.php b/src/controller/MaintenanceController.php index 1f8fadd..5b67fa8 100644 --- a/src/controller/MaintenanceController.php +++ b/src/controller/MaintenanceController.php | |||
| @@ -103,7 +103,7 @@ class MaintenanceController | |||
| 103 | if(pathinfo($selected_file)['extension'] !== 'sql'){ // pas censé se produire en fait | 103 | if(pathinfo($selected_file)['extension'] !== 'sql'){ // pas censé se produire en fait |
| 104 | throw new Exception("charger un fichier au format SQL"); | 104 | throw new Exception("charger un fichier au format SQL"); |
| 105 | } | 105 | } |
| 106 | Backup::restoreDatabase($entityManager, $selected_file); | 106 | Backup::restoreDatabase($entityManager, $selected_file, ['user']); |
| 107 | 107 | ||
| 108 | $_SESSION['flash_message'] = "La base de données a été restaurée avec succès !!"; | 108 | $_SESSION['flash_message'] = "La base de données a été restaurée avec succès !!"; |
| 109 | } | 109 | } |
| @@ -134,7 +134,7 @@ class MaintenanceController | |||
| 134 | $uploaded_file->move(Backup::$backup_dir, $server_place); | 134 | $uploaded_file->move(Backup::$backup_dir, $server_place); |
| 135 | 135 | ||
| 136 | // s'en servir | 136 | // s'en servir |
| 137 | Backup::restoreDatabase($entityManager, $server_place); | 137 | Backup::restoreDatabase($entityManager, $server_place, ['user']); |
| 138 | 138 | ||
| 139 | $_SESSION['flash_message'] = "La base de données a été restaurée avec succès !!"; | 139 | $_SESSION['flash_message'] = "La base de données a été restaurée avec succès !!"; |
| 140 | } | 140 | } |
diff --git a/src/service/Backup.php b/src/service/Backup.php index 45593bb..c30ce5b 100644 --- a/src/service/Backup.php +++ b/src/service/Backup.php | |||
| @@ -156,8 +156,7 @@ class Backup | |||
| 156 | } | 156 | } |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | // pattern "template method" | 159 | static public function restoreDatabase(EntityManager $entityManager, string $file_name, array $exclusion_list = []): void |
| 160 | static public function restoreDatabase(EntityManager $entityManager, string $file_name): void | ||
| 161 | { | 160 | { |
| 162 | // création d'un backup de sécurité non écrasable | 161 | // création d'un backup de sécurité non écrasable |
| 163 | $date = new DateTime; | 162 | $date = new DateTime; |
| @@ -168,20 +167,10 @@ class Backup | |||
| 168 | $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()'); | 167 | $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()'); |
| 169 | $engine = stripos($version, 'mariadb') !== false ? 'mariadb' : 'mysql'; | 168 | $engine = stripos($version, 'mariadb') !== false ? 'mariadb' : 'mysql'; |
| 170 | 169 | ||
| 171 | // choisir les tables à restaurer | 170 | $tables = self::getDBListOfTables($entityManager, $exclusion_list); // choisir les tables à effacer et restaurer, exclure "user" |
| 172 | $tables = $entityManager->getConnection()->createSchemaManager()->listTableNames(); | ||
| 173 | foreach($tables as $key => $elem){ | ||
| 174 | if($elem === TABLE_PREFIX . 'user'){ | ||
| 175 | unset($tables[$key]); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | // sécurité cas pas normal | ||
| 179 | if(empty($tables)){ | ||
| 180 | throw new RuntimeException("Aucune table à supprimer"); | ||
| 181 | } | ||
| 182 | 171 | ||
| 183 | $tmp = tempnam('../var', 'tmp_db_codes_'); // crée un fichier avec un nom aléatoire et des droits 600 (concurrence) | 172 | $tmp_db_codes = tempnam('../var', 'tmp_db_codes_'); // crée un fichier avec un nom aléatoire et des droits 600 (concurrence) |
| 184 | file_put_contents($tmp, | 173 | file_put_contents($tmp_db_codes, |
| 185 | "[client]\n | 174 | "[client]\n |
| 186 | user=" . Config::$user . "\n | 175 | user=" . Config::$user . "\n |
| 187 | password=" . Config::$password . "\n | 176 | password=" . Config::$password . "\n |
| @@ -191,31 +180,53 @@ class Backup | |||
| 191 | 180 | ||
| 192 | $command = new Process([ | 181 | $command = new Process([ |
| 193 | $engine, // mariadb ou mysql | 182 | $engine, // mariadb ou mysql |
| 194 | '--defaults-extra-file=' . $tmp, // pour ne pas enregistrer les codes dans l'historique de la console ou dans les processus de l'OS | 183 | '--defaults-extra-file=' . $tmp_db_codes, // pour ne pas enregistrer les codes dans l'historique de la console ou dans les processus de l'OS |
| 195 | Config::$database | 184 | Config::$database |
| 196 | ]); | 185 | ]); |
| 197 | $command->setInput(file_get_contents(Backup::$backup_dir . '/' . $file_name)); // l'entrée < | 186 | $command->setInput(file_get_contents(Backup::$backup_dir . '/' . $file_name)); // l'entrée < |
| 198 | 187 | ||
| 199 | 188 | // utiliser une liste de tables à exclure dynamique | |
| 200 | try{ | 189 | try{ |
| 201 | // tout effacer | 190 | // tout effacer |
| 202 | $tables_with_backquotes = array_map(fn($t) => '`' . $t . '`', $tables); | 191 | $tables_with_backquotes = array_map(fn($t) => '`' . $t . '`', $tables); |
| 203 | $sql = "SET FOREIGN_KEY_CHECKS=0; DROP TABLE " . implode(', ', $tables_with_backquotes) . "; SET FOREIGN_KEY_CHECKS=1;"; | 192 | if(!empty($tables_with_backquotes)){ |
| 204 | $entityManager->getConnection()->executeStatement($sql); | 193 | $sql = "SET FOREIGN_KEY_CHECKS=0; DROP TABLE " . implode(', ', $tables_with_backquotes) . "; SET FOREIGN_KEY_CHECKS=1;"; |
| 194 | $entityManager->getConnection()->executeStatement($sql); | ||
| 195 | } | ||
| 205 | 196 | ||
| 206 | // la table user restante va poser problème | 197 | // copie des tables à ne pas restaurer |
| 207 | $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . 'user` TO `' . TABLE_PREFIX . 'user_dont_touch`;'); | 198 | foreach($exclusion_list as $excluded){ |
| 199 | $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . $excluded . '` TO `' . TABLE_PREFIX . $excluded . '_dont_touch`;'); | ||
| 200 | } | ||
| 208 | 201 | ||
| 209 | // restaurer | 202 | // restaurer |
| 210 | $command->mustRun(); // comme run() mais lance une ProcessFailedException | 203 | $command->mustRun(); // comme run() mais lance une ProcessFailedException |
| 211 | 204 | ||
| 212 | // remettre table user comme avant | 205 | // remettre table user comme avant |
| 213 | $entityManager->getConnection()->executeStatement('DROP TABLE `' . TABLE_PREFIX . 'user`;'); | 206 | foreach($exclusion_list as $excluded){ |
| 214 | $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . 'user_dont_touch` TO `' . TABLE_PREFIX . 'user`;'); | 207 | $entityManager->getConnection()->executeStatement('DROP TABLE `' . TABLE_PREFIX . $excluded . '`;'); |
| 208 | $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . $excluded . '_dont_touch` TO `' . TABLE_PREFIX . $excluded . '`;'); | ||
| 209 | } | ||
| 215 | } | 210 | } |
| 216 | finally{ | 211 | finally{ |
| 217 | // exécuté même quand situé après "return" | 212 | // exécuté même quand situé après "return" |
| 218 | unlink($tmp); | 213 | unlink($tmp_db_codes); |
| 219 | } | 214 | } |
| 220 | } | 215 | } |
| 216 | |||
| 217 | static private function getDBListOfTables(EntityManager $entityManager, array $exclusion_list = []): array | ||
| 218 | { | ||
| 219 | $tables = $entityManager->getConnection()->createSchemaManager()->listTableNames(); | ||
| 220 | foreach($tables as $key => $elem){ | ||
| 221 | foreach($exclusion_list as $excluded){ | ||
| 222 | if(!is_string($excluded)){ // cas pas du tout censé arriver! | ||
| 223 | throw new LogicException("Un nom de table doit etre une chaîne de caractères."); | ||
| 224 | } | ||
| 225 | if($elem === TABLE_PREFIX . $excluded){ | ||
| 226 | unset($tables[$key]); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | return $tables; | ||
| 231 | } | ||
| 221 | } \ No newline at end of file | 232 | } \ No newline at end of file |
