aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/mysqldump.php2
-rw-r--r--public/js/maintenance.js4
-rw-r--r--src/controller/MaintenanceController.php4
-rw-r--r--src/service/Backup.php75
4 files changed, 73 insertions, 12 deletions
diff --git a/bin/mysqldump.php b/bin/mysqldump.php
index 4356a81..b7ae3ef 100644
--- a/bin/mysqldump.php
+++ b/bin/mysqldump.php
@@ -9,5 +9,5 @@ require "../vendor/autoload.php";
9Config::load('../config/config.ini'); 9Config::load('../config/config.ini');
10require '../src/model/doctrine-bootstrap.php'; 10require '../src/model/doctrine-bootstrap.php';
11 11
12$file_name = Backup::mySQLdump($entityManager); // créer un nouveau backup 12$file_name = Backup::mySQLdump($entityManager, 'console'); // créer un nouveau backup
13echo realpath($file_name) . "\n"; \ No newline at end of file 13echo realpath($file_name) . "\n"; \ No newline at end of file
diff --git a/public/js/maintenance.js b/public/js/maintenance.js
index 87f4aec..3d3d5e8 100644
--- a/public/js/maintenance.js
+++ b/public/js/maintenance.js
@@ -1,3 +1,5 @@
1// js/maintenance.js
2
1function displayLogs(){ 3function displayLogs(){
2 const log_table = getElementOrThrow('log_table'); 4 const log_table = getElementOrThrow('log_table');
3 5
@@ -41,4 +43,4 @@ function cleanLogs(){
41} 43}
42 44
43// notification après restauration 45// notification après restauration
44 46// et éventuellement récupérer le message de l'exception d'une autre manière
diff --git a/src/controller/MaintenanceController.php b/src/controller/MaintenanceController.php
index c62b21b..83304de 100644
--- a/src/controller/MaintenanceController.php
+++ b/src/controller/MaintenanceController.php
@@ -81,7 +81,7 @@ class MaintenanceController
81 static public function downloadSQL(EntityManager $entityManager, UploadedFile $uploaded_file): void 81 static public function downloadSQL(EntityManager $entityManager, UploadedFile $uploaded_file): void
82 { 82 {
83 if(pathinfo($uploaded_file->getClientOriginalName())['extension'] !== 'sql'){ 83 if(pathinfo($uploaded_file->getClientOriginalName())['extension'] !== 'sql'){
84 throw new Exception("charger un fichier au format SQL"); 84 throw new Exception("Charger un fichier au format SQL");
85 } 85 }
86 //echo $uploaded_file->getSize(); // à garder de côté au cas où 86 //echo $uploaded_file->getSize(); // à garder de côté au cas où
87 87
@@ -89,7 +89,7 @@ class MaintenanceController
89 89
90 try{ 90 try{
91 // enregistrer le fichier 91 // enregistrer le fichier
92 var_dump($uploaded_file->move(Backup::$backup_dir, $server_place)); 92 $uploaded_file->move(Backup::$backup_dir, $server_place);
93 93
94 // s'en servir 94 // s'en servir
95 Backup::restoreDatabase($entityManager, $server_place); 95 Backup::restoreDatabase($entityManager, $server_place);
diff --git a/src/service/Backup.php b/src/service/Backup.php
index 63368b5..1b44351 100644
--- a/src/service/Backup.php
+++ b/src/service/Backup.php
@@ -9,7 +9,7 @@ use Symfony\Component\Process\Process; // protection injection dans le shell
9class Backup 9class Backup
10{ 10{
11 static public string $backup_dir = '../var/backups'; 11 static public string $backup_dir = '../var/backups';
12 static private int $amount_to_keep = 30; 12 static private int $amount_to_keep = 20;
13 13
14 static public function mySQLdump(EntityManager $entityManager, string $type): string 14 static public function mySQLdump(EntityManager $entityManager, string $type): string
15 { 15 {
@@ -81,19 +81,78 @@ class Backup
81 return $backup_list[count($backup_list) - 1]; 81 return $backup_list[count($backup_list) - 1];
82 } 82 }
83 83
84 static public function cleanBackups(): void { 84 static public function cleanBackups(): void
85 {
85 $files = glob(self::$backup_dir . '/*.sql'); 86 $files = glob(self::$backup_dir . '/*.sql');
86 usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a)); // filemtime = date de dernière modification 87 //usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a)); // filemtime = date de dernière modification
87 $files_to_delete = array_slice($files, self::$amount_to_keep); 88 arsort($files);
88 foreach($files_to_delete as $file){ 89
89 unlink($file); 90 // tri par nom de BDD puis par date
91 $sorted_files = [];
92 $list_by_database = []; // pour le nettoyage 2
93 foreach($files as $file){
94 $exploded = explode('_', basename($file));
95 $sorted_files[$exploded[0]][$exploded[1]][] = $file;
96 $list_by_database[$exploded[0]][] = $file;
97 }
98
99 $today = new DateTime()->format('Y-m-d');
100 foreach($sorted_files as $db_name => $from_one_database){
101 // on garde une "quantité à garder" par BDD
102 if(count($from_one_database) > self::$amount_to_keep){
103 // nettoyage 1
104 foreach($from_one_database as $date => $with_same_date){
105 // pas touche à aujourd'hui
106 if($date != $today){
107 self::cleanBackupsByPriority($with_same_date);
108 }
109 }
110 // nettoyage 2
111 $files_to_delete = array_slice($list_by_database[$db_name], self::$amount_to_keep);
112 foreach($files_to_delete as $file){
113 unlink($file);
114 }
115 }
116 }
117 }
118
119 // conserver un seul backup par jour choisi dans cet ordre de préférence: console => before-restore => download => auto
120 // cet ordre correspond à: volonté de l'utilisateur => état du jour avant changement => volonté de changement => automatique sans contrôle
121 static private function cleanBackupsByPriority(array $files): void
122 {
123 $priorities = [
124 'console' => 1,
125 'before-restore' => 2,
126 'uploaded' => 3,
127 'auto' => 4,
128 ];
129 $best_priority = PHP_INT_MAX;
130
131 // recherche du fichier à conserver
132 $to_keep = null;
133 foreach($files as $file){
134 foreach($priorities as $keyword => $priority){
135 if(str_contains(basename($file), $keyword) && $priority < $best_priority){
136 $best_priority = $priority;
137 $to_keep = $file;
138 break;
139 }
140 }
141 }
142 // suppression des autres
143 foreach($files as $file){
144 if($file !== $to_keep){
145 unlink($file);
146 }
90 } 147 }
91 } 148 }
92 149
93 static public function restoreDatabase(EntityManager $entityManager, string $file_name): void 150 static public function restoreDatabase(EntityManager $entityManager, string $file_name): void
94 { 151 {
95 // backup de sécurité 152 // création d'un backup de sécurité non écrasable
96 Backup::mySQLdump($entityManager, 'before-restore'); 153 if(!file_exists(self::$backup_dir . '/' . Config::$database . '_' . new DateTime()->format('Y-m-d') . '_before-restore.sql')){
154 Backup::mySQLdump($entityManager, 'before-restore');
155 }
97 156
98 $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()'); 157 $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()');
99 $engine = stripos($version, 'mariadb') !== false ? 'mariadb' : 'mysql'; 158 $engine = stripos($version, 'mariadb') !== false ? 'mariadb' : 'mysql';