diff options
| author | polo <ordipolo@gmx.fr> | 2026-05-10 17:01:21 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2026-05-10 17:01:21 +0200 |
| commit | 895cf7a438929f74c2e11996667685245a571f2a (patch) | |
| tree | 5dfad9d5e0d2f4a802482f5883dd4673ed971238 | |
| parent | 2c47085b27253c4ad2d062d15c18c3a8c7591298 (diff) | |
| download | cms-895cf7a438929f74c2e11996667685245a571f2a.tar.gz cms-895cf7a438929f74c2e11996667685245a571f2a.tar.bz2 cms-895cf7a438929f74c2e11996667685245a571f2a.zip | |
partie client de la restauration de BDD, script bin/mysqldump.php, changements permissions dossiers, renommage ViewDirector
| -rwxr-xr-x | bin/mode.php | 65 | ||||
| -rw-r--r-- | bin/mysqldump.php | 13 | ||||
| -rw-r--r-- | public/css/maintenance.css | 8 | ||||
| -rw-r--r-- | public/index.php | 2 | ||||
| -rw-r--r-- | src/controller/MaintenanceController.php | 2 | ||||
| -rw-r--r-- | src/controller/ViewDirector.php (renamed from src/controller/ViewController.php) | 7 | ||||
| -rw-r--r-- | src/service/Backup.php | 22 | ||||
| -rw-r--r-- | src/service/Installation.php | 54 | ||||
| -rw-r--r-- | src/service/router.php | 2 | ||||
| -rw-r--r-- | src/view/MaintenanceBuilder.php | 7 | ||||
| -rw-r--r-- | src/view/templates/maintenance.php | 20 |
11 files changed, 113 insertions, 89 deletions
diff --git a/bin/mode.php b/bin/mode.php deleted file mode 100755 index 552ce4e..0000000 --- a/bin/mode.php +++ /dev/null | |||
| @@ -1,65 +0,0 @@ | |||
| 1 | #!/usr/bin/env php | ||
| 2 | <?php | ||
| 3 | // bin/mode.php | ||
| 4 | |||
| 5 | declare(strict_types=1); | ||
| 6 | |||
| 7 | use App\Entity\AppMetadata; | ||
| 8 | use Doctrine\ORM\EntityManager; | ||
| 9 | |||
| 10 | |||
| 11 | chdir(dirname(__FILE__)); // pour être au même niveau que l'appli dans /public | ||
| 12 | require "../vendor/autoload.php"; | ||
| 13 | Config::load('../config/config.ini'); // pour TABLE_PREFIX | ||
| 14 | require '../src/model/doctrine-bootstrap.php'; | ||
| 15 | |||
| 16 | const ALLOWED_MODES = ['run', 'maintenance']; | ||
| 17 | |||
| 18 | // aide | ||
| 19 | $aide = "Usage : php bin/mode.php <mode>\nModes disponibles : " . implode(', ', ALLOWED_MODES) . "\n"; | ||
| 20 | // version avec deux paramètres proposée par claude | ||
| 21 | /*$aide = "Usage : php bin/mode.php <mode> [--by <auteur>] | ||
| 22 | Modes disponibles : " . implode(', ', ALLOWED_MODES) . " | ||
| 23 | Exemple : php bin/mode.php maintenance --by alice\n";*/ | ||
| 24 | if($argc < 2 || in_array($argv[1], ['--help', '-h'])){ | ||
| 25 | echo $aide; | ||
| 26 | exit(0); | ||
| 27 | } | ||
| 28 | |||
| 29 | // validation du mode | ||
| 30 | if(!in_array($argv[1], ALLOWED_MODES)){ | ||
| 31 | echo "Erreur : mode '$argv[1]' invalide.\n"; | ||
| 32 | echo "Modes disponibles : " . implode(', ', ALLOWED_MODES) . "\n"; | ||
| 33 | exit(1); | ||
| 34 | } | ||
| 35 | |||
| 36 | // paramètre --by | ||
| 37 | /*$by = 'cli'; | ||
| 38 | for ($i = 2; $i < $argc; $i++) { | ||
| 39 | if ($argv[$i] === '--by' && isset($argv[$i + 1])) { | ||
| 40 | $by = $argv[$i + 1]; | ||
| 41 | break; | ||
| 42 | } | ||
| 43 | }*/ | ||
| 44 | |||
| 45 | // changement BDD | ||
| 46 | try{ | ||
| 47 | AppMode::load($entityManager); | ||
| 48 | $current = AppMode::get(); | ||
| 49 | |||
| 50 | if($current === $argv[1]){ | ||
| 51 | echo "Le mode est déjà '$argv[1]', aucun changement.\n"; | ||
| 52 | exit(0); | ||
| 53 | } | ||
| 54 | |||
| 55 | AppMode::set($entityManager, $argv[1]); | ||
| 56 | echo "Mode changé : '$current' => '$argv[1]'\n"; | ||
| 57 | |||
| 58 | // le mode deux paramètres permettra d'indiquer son nom et automatiquement de d'enregistrer la date du changement | ||
| 59 | //AppMode::set($entityManager, $argv[1], 'system'); | ||
| 60 | //echo "Mode changé : '$current' => '$argv[1]' (par $by)\n"; | ||
| 61 | } | ||
| 62 | catch(LogicException $e){ | ||
| 63 | echo "Erreur : " . $e->getMessage() . "\n"; | ||
| 64 | exit(1); | ||
| 65 | } \ No newline at end of file | ||
diff --git a/bin/mysqldump.php b/bin/mysqldump.php new file mode 100644 index 0000000..4356a81 --- /dev/null +++ b/bin/mysqldump.php | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #!/usr/bin/env php | ||
| 2 | <?php | ||
| 3 | // bin/mysqldump.php | ||
| 4 | |||
| 5 | declare(strict_types=1); | ||
| 6 | |||
| 7 | chdir(dirname(__FILE__)); | ||
| 8 | require "../vendor/autoload.php"; | ||
| 9 | Config::load('../config/config.ini'); | ||
| 10 | require '../src/model/doctrine-bootstrap.php'; | ||
| 11 | |||
| 12 | $file_name = Backup::mySQLdump($entityManager); // créer un nouveau backup | ||
| 13 | echo realpath($file_name) . "\n"; \ No newline at end of file | ||
diff --git a/public/css/maintenance.css b/public/css/maintenance.css index 887f3a7..8fd0601 100644 --- a/public/css/maintenance.css +++ b/public/css/maintenance.css | |||
| @@ -19,4 +19,12 @@ | |||
| 19 | .maintenance table th, .maintenance table td | 19 | .maintenance table th, .maintenance table td |
| 20 | { | 20 | { |
| 21 | border: 1px black solid; | 21 | border: 1px black solid; |
| 22 | } | ||
| 23 | .maintenance select, .maintenance input[type="file"]::file-selector-button | ||
| 24 | { | ||
| 25 | color: #ff1d04; | ||
| 26 | font-size: medium; | ||
| 27 | border-radius: 4px; | ||
| 28 | background-color: white; | ||
| 29 | border: lightgrey 2px outset; | ||
| 22 | } \ No newline at end of file | 30 | } \ No newline at end of file |
diff --git a/public/index.php b/public/index.php index bd6725e..591fff7 100644 --- a/public/index.php +++ b/public/index.php | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | /* plan d'action pour "symfonyfier" le site | 4 | /* plan d'action pour "symfonyfier" le site |
| 5 | A - | 5 | A - |
| 6 | 1/ de vrais contrôleurs: classes et méthodes prenant une requête en entrée et retournant une réponse | 6 | 1/ de vrais contrôleurs: classes et méthodes prenant une requête en entrée et retournant une réponse |
| 7 | (début de séparation contrôleurs et classes métier, exemple: ViewController/Model) | 7 | (début de séparation contrôleurs et classes métier) |
| 8 | 2/ routeur structuré: méthodes GET et POST, content-type, admin | 8 | 2/ routeur structuré: méthodes GET et POST, content-type, admin |
| 9 | 3/ routeur amélioré: pré-routage avec méthodes HTTP: GET, HEAD, POST, PUT, PATCH, DELETE, etc | 9 | 3/ routeur amélioré: pré-routage avec méthodes HTTP: GET, HEAD, POST, PUT, PATCH, DELETE, etc |
| 10 | 4/ réécriture avec les classes Request et Response sans toucher les liens | 10 | 4/ réécriture avec les classes Request et Response sans toucher les liens |
diff --git a/src/controller/MaintenanceController.php b/src/controller/MaintenanceController.php index fca45f1..c60ca1c 100644 --- a/src/controller/MaintenanceController.php +++ b/src/controller/MaintenanceController.php | |||
| @@ -52,7 +52,7 @@ class MaintenanceController | |||
| 52 | static public function getLastDump(EntityManager $entityManager): void | 52 | static public function getLastDump(EntityManager $entityManager): void |
| 53 | { | 53 | { |
| 54 | try{ | 54 | try{ |
| 55 | $file_path = Backup::mySQLdump($entityManager); | 55 | $file_path = Backup::getLastBackupName(); |
| 56 | header('Content-Type: application/octet-stream'); // signifie fichier quelconque, du binaire quoi! | 56 | header('Content-Type: application/octet-stream'); // signifie fichier quelconque, du binaire quoi! |
| 57 | header('Content-Disposition: attachment; filename="' . basename($file_path) . '"'); // pour provoquer un téléchargement et non pour afficher | 57 | header('Content-Disposition: attachment; filename="' . basename($file_path) . '"'); // pour provoquer un téléchargement et non pour afficher |
| 58 | header('Content-Length: ' . filesize($file_path)); // peut servir côté client (barre de progression...) | 58 | header('Content-Length: ' . filesize($file_path)); // peut servir côté client (barre de progression...) |
diff --git a/src/controller/ViewController.php b/src/controller/ViewDirector.php index cf3477c..6883b73 100644 --- a/src/controller/ViewController.php +++ b/src/controller/ViewDirector.php | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | <?php | 1 | <?php |
| 2 | // src/view/ViewController.php | 2 | // src/view/ViewDirector.php |
| 3 | // | 3 | // |
| 4 | // génère le HTML avec des Builder | 4 | // génère le HTML avec des Builder |
| 5 | 5 | ||
| @@ -10,7 +10,7 @@ use Doctrine\ORM\EntityManager; | |||
| 10 | use Symfony\Component\HttpFoundation\Request; | 10 | use Symfony\Component\HttpFoundation\Request; |
| 11 | use Symfony\Component\HttpFoundation\Response; | 11 | use Symfony\Component\HttpFoundation\Response; |
| 12 | 12 | ||
| 13 | class ViewController extends AbstractBuilder // ViewController est aussi le premier Builder | 13 | class ViewDirector extends AbstractBuilder // ViewDirector est aussi le premier Builder |
| 14 | { | 14 | { |
| 15 | static public Node $root_node; | 15 | static public Node $root_node; |
| 16 | 16 | ||
| @@ -61,6 +61,9 @@ class ViewController extends AbstractBuilder // ViewController est aussi le prem | |||
| 61 | if(CURRENT_PAGE === 'article' && !IS_ADMIN && self::$root_node->getNodeByName('main')->getAdoptedChild() === null){ | 61 | if(CURRENT_PAGE === 'article' && !IS_ADMIN && self::$root_node->getNodeByName('main')->getAdoptedChild() === null){ |
| 62 | return new Response($this->html, 302); | 62 | return new Response($this->html, 302); |
| 63 | } | 63 | } |
| 64 | elseif(CURRENT_PAGE === 'maintenance'){ | ||
| 65 | Backup::mySQLdump($entityManager); // créer un nouveau backup | ||
| 66 | } | ||
| 64 | 67 | ||
| 65 | 68 | ||
| 66 | /* 4/ construction de la page avec builders et vues */ | 69 | /* 4/ construction de la page avec builders et vues */ |
diff --git a/src/service/Backup.php b/src/service/Backup.php index d628c27..313d1f6 100644 --- a/src/service/Backup.php +++ b/src/service/Backup.php | |||
| @@ -37,7 +37,12 @@ class Backup | |||
| 37 | ]); | 37 | ]); |
| 38 | 38 | ||
| 39 | try{ | 39 | try{ |
| 40 | // unlink et chmod permettent que le serveur et l'utilisateur appelant bin/mysqldump.php réussissent | ||
| 41 | if(file_exists($file_path)){ | ||
| 42 | unlink($file_path); | ||
| 43 | } | ||
| 40 | $command->mustRun(); // comme run() mais lance une ProcessFailedException | 44 | $command->mustRun(); // comme run() mais lance une ProcessFailedException |
| 45 | chmod($file_path, 0666); | ||
| 41 | return $file_path; | 46 | return $file_path; |
| 42 | } | 47 | } |
| 43 | finally{ | 48 | finally{ |
| @@ -59,6 +64,23 @@ class Backup | |||
| 59 | }*/ | 64 | }*/ |
| 60 | } | 65 | } |
| 61 | 66 | ||
| 67 | static public function getBackupList(): array | ||
| 68 | { | ||
| 69 | $backup_array = []; | ||
| 70 | foreach(scandir(Backup::$backup_dir) as $file){ | ||
| 71 | if($file[0] === '.'){ | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | $backup_array[] = $file; | ||
| 75 | } | ||
| 76 | return $backup_array; | ||
| 77 | } | ||
| 78 | static public function getLastBackupName(): string | ||
| 79 | { | ||
| 80 | $backup_list = self::getBackupList(); | ||
| 81 | return $backup_list[count($backup_list) - 1]; | ||
| 82 | } | ||
| 83 | |||
| 62 | static public function cleanBackups(): void { | 84 | static public function cleanBackups(): void { |
| 63 | $files = glob(self::$backup_dir . '/*.sql'); | 85 | $files = glob(self::$backup_dir . '/*.sql'); |
| 64 | usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a)); // filemtime = date de dernière modification | 86 | usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a)); // filemtime = date de dernière modification |
diff --git a/src/service/Installation.php b/src/service/Installation.php index eb4b6db..995ed4a 100644 --- a/src/service/Installation.php +++ b/src/service/Installation.php | |||
| @@ -12,10 +12,14 @@ class Installation | |||
| 12 | // ajouter plus tard zlib pour la compression des backups | 12 | // ajouter plus tard zlib pour la compression des backups |
| 13 | foreach($extensions as $extension){ | 13 | foreach($extensions as $extension){ |
| 14 | if(!extension_loaded($extension)){ | 14 | if(!extension_loaded($extension)){ |
| 15 | echo("<p>l'extension <b>" . $extension . '</b> est manquante</p>'); | 15 | echo("<p>l'extension <b>" . $extension . "</b> est manquante.</p>"); |
| 16 | $flag = true; | 16 | $flag = true; |
| 17 | } | 17 | } |
| 18 | } | 18 | } |
| 19 | if(!class_exists(DOMDocument::class)){ // théoriquement plus fiable que extension_loaded() | ||
| 20 | echo("<p>l'extension <b>dom</b> est manquante.</p>"); | ||
| 21 | $flag = true; | ||
| 22 | } | ||
| 19 | 23 | ||
| 20 | /*if(!extension_loaded('imagick') && !extension_loaded('gd')){ | 24 | /*if(!extension_loaded('imagick') && !extension_loaded('gd')){ |
| 21 | echo("<p>il manque une de ces extensions au choix pour le traitement des images: <b>imagick</b> (de préférence) ou <b>gd</b>.</p>"); | 25 | echo("<p>il manque une de ces extensions au choix pour le traitement des images: <b>imagick</b> (de préférence) ou <b>gd</b>.</p>"); |
| @@ -33,27 +37,40 @@ class Installation | |||
| 33 | static public function checkFilesAndFoldersRights(): void | 37 | static public function checkFilesAndFoldersRights(): void |
| 34 | { | 38 | { |
| 35 | // -- droits des fichiers et dossiers -- | 39 | // -- droits des fichiers et dossiers -- |
| 36 | $droits_dossiers = 0755; | 40 | $droits_dossiers = 0777; |
| 37 | $droits_fichiers = 0644; | ||
| 38 | 41 | ||
| 42 | $flag = false; | ||
| 39 | if(!file_exists('user_data')){ | 43 | if(!file_exists('user_data')){ |
| 40 | // créer le dossier user_data | 44 | try{ |
| 41 | mkdir('user_data/'); | 45 | mkdir('user_data/'); |
| 42 | chmod('user_data/', $droits_dossiers); | 46 | chmod('user_data/', $droits_dossiers); |
| 43 | echo '<p style="color: red;">Le dossier public/user_data introuvable et le serveur n\'a pas la permission de le créer.<br> | 47 | } |
| 44 | Pour faire ça bien:<br>sudo -u "serveur web" mkdir /chemin/du/site/public/user_data</p> | 48 | catch(Exception $e){ |
| 45 | <p>Aide: "serveur web" se nomme "www-data" sur debian et ubuntu, il s\'appelera "http" sur d\'autres distributions.</p>'; | 49 | echo '<p style="color: red;">Le dossier public/user_data introuvable et le serveur n\'a pas la permission de le créer.<br> |
| 46 | die; | 50 | Pour faire ça bien:<br>sudo -u "serveur web" mkdir /chemin/du/site/public/user_data</p>'; |
| 51 | echo $e; | ||
| 52 | $flag = true; | ||
| 53 | } | ||
| 47 | } | 54 | } |
| 48 | if(!file_exists('../var')){ | 55 | if(!file_exists('../var')){ |
| 49 | mkdir('../var'); | 56 | try{ |
| 50 | chmod('../var', $droits_dossiers); | 57 | mkdir('../var'); |
| 51 | // | 58 | chmod('../var', $droits_dossiers); |
| 59 | } | ||
| 60 | catch(Exception $e){ | ||
| 61 | echo $e; | ||
| 62 | $flag = true; | ||
| 63 | } | ||
| 52 | } | 64 | } |
| 53 | if(!file_exists('../var/backups')){ | 65 | if(!file_exists('../var/backups')){ |
| 54 | mkdir('../var/backups'); | 66 | try{ |
| 55 | chmod('../var/backups', $droits_dossiers); | 67 | mkdir('../var/backups'); |
| 56 | // | 68 | chmod('../var/backups', $droits_dossiers); // autoriser à la fois le serveur et les scripts dans bin/ |
| 69 | } | ||
| 70 | catch(Exception $e){ | ||
| 71 | echo $e; | ||
| 72 | $flag = true; | ||
| 73 | } | ||
| 57 | } | 74 | } |
| 58 | 75 | ||
| 59 | // droits 600 pour celui-ci | 76 | // droits 600 pour celui-ci |
| @@ -63,7 +80,7 @@ class Installation | |||
| 63 | echo '<p>Il doit obligatoirement contenir les codes de la base de données, le protocole http ou https (et éventuellement le port) utilisé pour créer les liens internes.<br> | 80 | echo '<p>Il doit obligatoirement contenir les codes de la base de données, le protocole http ou https (et éventuellement le port) utilisé pour créer les liens internes.<br> |
| 64 | Un modèle est disponible, il s\'agit du fichier config/config-template.ini</p> | 81 | Un modèle est disponible, il s\'agit du fichier config/config-template.ini</p> |
| 65 | <p>Ce fichier a une importance critique. Si vous le pouvez faites en sorte que le serveur en soit le propriétaire et donner lui des droits 600.</p>'; | 82 | <p>Ce fichier a une importance critique. Si vous le pouvez faites en sorte que le serveur en soit le propriétaire et donner lui des droits 600.</p>'; |
| 66 | die; | 83 | $flag = true; |
| 67 | } | 84 | } |
| 68 | /*else{ | 85 | /*else{ |
| 69 | // propriétaire du fichier | 86 | // propriétaire du fichier |
| @@ -78,6 +95,9 @@ class Installation | |||
| 78 | } | 95 | } |
| 79 | } | 96 | } |
| 80 | }*/ | 97 | }*/ |
| 98 | if($flag){ | ||
| 99 | die; | ||
| 100 | } | ||
| 81 | 101 | ||
| 82 | // tester les liens internes | 102 | // tester les liens internes |
| 83 | // | 103 | // |
diff --git a/src/service/router.php b/src/service/router.php index 6973656..98f8fd6 100644 --- a/src/service/router.php +++ b/src/service/router.php | |||
| @@ -52,7 +52,7 @@ if($request->getMethod() === 'GET'){ | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | // construction d'une page | 54 | // construction d'une page |
| 55 | $response = (new ViewController)->buildView($entityManager, $request); // utilise Model | 55 | $response = (new ViewDirector)->buildView($entityManager, $request); // utilise Model |
| 56 | // parenthèses nécéssaires autour de l'instanciation pour PHP < 8.4 | 56 | // parenthèses nécéssaires autour de l'instanciation pour PHP < 8.4 |
| 57 | } | 57 | } |
| 58 | 58 | ||
diff --git a/src/view/MaintenanceBuilder.php b/src/view/MaintenanceBuilder.php index f5c60ed..d9c52b1 100644 --- a/src/view/MaintenanceBuilder.php +++ b/src/view/MaintenanceBuilder.php | |||
| @@ -10,6 +10,13 @@ class MaintenanceBuilder extends AbstractBuilder | |||
| 10 | public function __construct(Node $node){ | 10 | public function __construct(Node $node){ |
| 11 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; | 11 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; |
| 12 | 12 | ||
| 13 | // noter qu'un backup vient d'être créé depuis ViewDirector | ||
| 14 | $backup_array = Backup::getBackupList(); | ||
| 15 | $backup_options = ''; | ||
| 16 | for($i = count($backup_array) - 1; $i >= 0; $i--){ | ||
| 17 | $backup_options .= '<option value="' . $backup_array[$i] . '">' . $backup_array[$i] . '</option>'; | ||
| 18 | } | ||
| 19 | |||
| 13 | if(file_exists($viewFile)){ | 20 | if(file_exists($viewFile)){ |
| 14 | ob_start(); | 21 | ob_start(); |
| 15 | require $viewFile; | 22 | require $viewFile; |
diff --git a/src/view/templates/maintenance.php b/src/view/templates/maintenance.php index 3501fa4..58e04c0 100644 --- a/src/view/templates/maintenance.php +++ b/src/view/templates/maintenance.php | |||
| @@ -19,9 +19,25 @@ | |||
| 19 | <div class="basic_div"> | 19 | <div class="basic_div"> |
| 20 | <p> | 20 | <p> |
| 21 | <a href="<?= new URL(['action' => 'get_mysqldump']) ?>"> | 21 | <a href="<?= new URL(['action' => 'get_mysqldump']) ?>"> |
| 22 | <button id="get_mysqldump">Télécharger la base de données</button> | 22 | <button id="get_mysqldump">Télécharger une sauvegarde de la base de données</button> |
| 23 | </a><br> | 23 | </a><br> |
| 24 | <i>Réalise un "mysqldump", vous obtiendrez un unique fichier contenant toute la BDD.</i> | 24 | <i>Obtenir un fichier SQL à conserver sur votre ordinateur. Une sauvegarde est réalisée à chaque visite de cette page.</i> |
| 25 | </p> | ||
| 26 | </div> | ||
| 27 | <div class="basic_div"> | ||
| 28 | <p>Restaurer la base de données à partir d'un fichier SQL.<br> | ||
| 29 | <i>Attention l'actuelle BDD sera écrasée!</i> | ||
| 30 | </p> | ||
| 31 | <p> | ||
| 32 | <label for="">Utiliser une sauvegarde conservée sur le serveur</label> | ||
| 33 | <select> | ||
| 34 | <?= $backup_options ?> | ||
| 35 | </select> | ||
| 36 | </p> | ||
| 37 | <p> | ||
| 38 | <label for="restore_sql_dump">Utiliser un fichier sur votre ordinateur:</label> | ||
| 39 | <input id="restore_sql_dump" type="file" accept=".sql" name="restore_sql_dump"> | ||
| 40 | |||
| 25 | </p> | 41 | </p> |
| 26 | </div> | 42 | </div> |
| 27 | 43 | ||
