aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2026-06-30 22:05:06 +0200
committerpolo <ordipolo@gmx.fr>2026-06-30 22:05:06 +0200
commit9021dc699874c46b72dcbe019ec1a4408fbf6d70 (patch)
tree9fdb40800547ecd9843ebd57ee069a13bf84eeed /src
parentde2488b7a45f63e128a4f2f393e1040323837a62 (diff)
downloadcms-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
Diffstat (limited to 'src')
-rw-r--r--src/controller/MaintenanceController.php4
-rw-r--r--src/service/Backup.php59
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