summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2021-09-08 02:09:34 +0200
committerpolo <ordipolo@gmx.fr>2021-09-08 02:09:34 +0200
commitcdf1bda847edd3e22e9fe817a802219ad8e0f626 (patch)
treeadbe2b35e9741a5db74491c85914f4c03d3d4c99
parent9a552c6b751f25bac9e816cf605fb972da8b9e27 (diff)
downloadmelaine-cdf1bda847edd3e22e9fe817a802219ad8e0f626.zip
vignette
-rw-r--r--controller/admin.php51
-rw-r--r--controller/ckeditor.php44
-rw-r--r--controller/visitor.php54
-rw-r--r--imageAJAX.php100
-rw-r--r--index.php29
-rw-r--r--model/Classes.php26
-rw-r--r--model/Image.php59
-rw-r--r--public/discographie.css32
-rw-r--r--public/donnees_hors_editeur.css4
-rw-r--r--public/melaine.css1
-rw-r--r--view/album.php2
-rw-r--r--view/discographie.php4
-rw-r--r--view/template-formulaires.php22
13 files changed, 214 insertions, 214 deletions
diff --git a/controller/admin.php b/controller/admin.php
index 3c2b613..ba6fd83 100644
--- a/controller/admin.php
+++ b/controller/admin.php
@@ -98,11 +98,6 @@ function discoEdit($numArticle, $suppression)
98 } 98 }
99 } 99 }
100 100
101 $albumsJSON = array_reverse($Album->readAll()); // lourd
102
103 // $albums contient un tableau de chaines JSON,
104 // on extrait de chacune 3 variables: titre, année, pochette
105
106 // traitements PHP pour l'éditeur 101 // traitements PHP pour l'éditeur
107 // sécurisation du contenu pré-existant inséré dans l'éditeur 102 // sécurisation du contenu pré-existant inséré dans l'éditeur
108 if($numArticle >= 0 && !$suppression) 103 if($numArticle >= 0 && !$suppression)
@@ -111,44 +106,58 @@ function discoEdit($numArticle, $suppression)
111 $texte = preparationCKeditor($numArticle, $texte); 106 $texte = preparationCKeditor($numArticle, $texte);
112 } 107 }
113 108
114 // changer les chaines JSON en tableaux 109
110 // contenu de tous les fichiers JSON (= tableau de chaines)
111 $albumsJSON = $Album->readAll();
112 // noms des fichiers JSON
113 $albumNamesJSON = $Album->getFileList();
114
115 // changer les chaines JSON en tableaux: titre, année, pochette
115 $i = 0; 116 $i = 0;
117 $annees = array();
116 foreach($albumsJSON as $oneAlbum) 118 foreach($albumsJSON as $oneAlbum)
117 { 119 {
118 $albumsJSON[$i] = json_decode($oneAlbum, true); 120 $albumsJSON[$i] = json_decode($oneAlbum, true);
121
122 // ajout des noms des fichiers JSON
123 $albumsJSON[$i][3] = $albumNamesJSON[$i];
124 $annees[$i] = $albumsJSON[$i][1];
119 $i++; 125 $i++;
120 } 126 }
127 // tri d'un tableau multidimensionnel
128 array_multisort($annees, $albumsJSON);
121 129
122 // on passe maintenant au contenu HTML 130 // on passe maintenant au contenu HTML
123 $albumNamesJSON = array_reverse($Album->getFileNames());
124 $Album->setFormat('html'); 131 $Album->setFormat('html');
125 $Album->makeFileList(); 132 $Album->makeFileList();
126 $albumNamesHTML = array_reverse($Album->getFileNames()); 133 $albumNamesHTML = $Album->getFileList();
127 134
128 // lien vers le HTML ou ancre? 135 // lien vers le HTML ou ancre?
129 // pour chaque album, détecter le fichier html 136 // pour chaque album, détecter le fichier html
130 // si non, ne fournir qu'un lien d'ancre pour la liste d'album 137 // si non, ne fournir qu'un lien d'ancre pour la liste d'album
131 $i = 0; 138 $i = 0;
132 $avecLien = []; 139 $avecLien = [];
133 foreach($albumNamesJSON as $oneAlbum) 140 foreach($albumsJSON as $oneAlbum)
134 { 141 {
135 // nom sans extension 142 // nom sans extension
136 $chemin = pathinfo($oneAlbum); 143 $chemin = pathinfo($oneAlbum[3]);
137 $nomJSONsansExt = $chemin['filename']; 144 $nomJSONsansExt = $chemin['filename'];
138 $chemin = pathinfo($albumNamesHTML[0]);
139 145
140 // détection 146 // au cas où la discographie ne contient aucun html
141 if(file_exists($chemin['dirname'] . '/' . $nomJSONsansExt . '.html')) 147 if(!empty($albumNamesHTML))
142 { 148 {
143 $lienAlbum[$i] = 'album&album_code=' . $nomJSONsansExt . '&album_name=' . $albumsJSON[$i][0]; 149 if(file_exists('data/discographie/html/' . $nomJSONsansExt . '.html'))
144 $avecLien[$i] = true; 150 {
151 $lienAlbum[$i] = 'album&album_code=' . $nomJSONsansExt . '&album_name=' . $albumsJSON[$i][0];
152 $avecLien[$i] = true;
153 }
154 else
155 {
156 $lienAlbum[$i] = 'discographie#' . $albumsJSON[$i][0];
157 $avecLien[$i] = false;
158 }
159 $i++;
145 } 160 }
146 else
147 {
148 $lienAlbum[$i] = 'discographie#' . $albumsJSON[$i][0];
149 $avecLien[$i] = false;
150 }
151 $i++;
152 } 161 }
153 162
154 // morceaux en HTML à assembler 163 // morceaux en HTML à assembler
diff --git a/controller/ckeditor.php b/controller/ckeditor.php
index 2e72be2..d07f2a2 100644
--- a/controller/ckeditor.php
+++ b/controller/ckeditor.php
@@ -87,7 +87,7 @@ function submitCKeditor($nomFichier)
87 { 87 {
88 $titre = $_POST['titre']; 88 $titre = $_POST['titre'];
89 $annee = $_POST['annee']; 89 $annee = $_POST['annee'];
90 $pochette = $_POST['pochette']; // une image 90 $pochette = $_FILES['upload']['name'];
91 91
92 // des formulaires simples 92 // des formulaires simples
93 $titre = htmLawed($titre, $configHtmLawed, $specHtmLawed); 93 $titre = htmLawed($titre, $configHtmLawed, $specHtmLawed);
@@ -95,36 +95,8 @@ function submitCKeditor($nomFichier)
95 $annee = htmLawed($annee, $configHtmLawed, $specHtmLawed); 95 $annee = htmLawed($annee, $configHtmLawed, $specHtmLawed);
96 $annee = trim($annee); 96 $annee = trim($annee);
97 97
98 // pochette
99 // Album->imageUpload();
100 // test formats jpg, jpeg, png, gif, tiff
101 // enregistrement du fichier
102 }
103
104 // lien sans http://
105 // un clic sur un lien dans l'éditeur affiche une infobulle montrant l'adresse cible du lien si celle-ci a déjà été précisée
106 // il est possible de cliquer sur ce lien, ce qui ouvre un onglet avec le site demandé
107 // toutefois si cette adresse est de type "domaine.fr" (sans http:// devant), le navigateur ne va pas rechercher un site mais un fichier comme si mon adresse était de type file:///fichier
108 // tomber ainsi sur une page d'erreur est déroutant:
109 // "ai-je perdu le texte que j'étais en train de taper?""
110 // solution 1 (mauvaise): activer la redirection en cas d'erreur 404 dans le .htaccess
111 // solution 2 (façon pop-up): fermer ce nouvel onglet avec echo '<SCRIPT>javascript:window.close()</SCRIPT>';
112 // pour faire passer par le .htaccess l'info comme quoi la page précédente comportait un éditeur ouvert...
113
114
115 // enregistrement
116 // var_dump($titre, $annee, $pochette, $contenu);
117 // die();
118
119 // modèle
120 if($page == 'discographie')
121 {
122 // on instancie avec l'enfant de OneArticle 98 // on instancie avec l'enfant de OneArticle
123 $Album = new Album($page); 99 $Album = new Album($page);
124
125 //var_dump($_GET['article']);
126 //var_dump($_POST);
127 //exit();
128 100
129 // enregistrement 101 // enregistrement
130 if($_GET['article'] == 0) 102 if($_GET['article'] == 0)
@@ -132,7 +104,7 @@ function submitCKeditor($nomFichier)
132 // page disco 104 // page disco
133 $Album->createVignette($titre, $annee, $pochette); 105 $Album->createVignette($titre, $annee, $pochette);
134 106
135 // page détail de l'album 107 // page de l'album
136 if(!empty($_POST['contenu'])) 108 if(!empty($_POST['contenu']))
137 { 109 {
138 $Album->create($contenu); 110 $Album->create($contenu);
@@ -143,7 +115,7 @@ function submitCKeditor($nomFichier)
143 // page disco 115 // page disco
144 $Album->updateVignette($titre, $annee, $pochette); 116 $Album->updateVignette($titre, $annee, $pochette);
145 117
146 // page détail de l'album 118 // page de l'album
147 if(isset($_POST['contenu'])) 119 if(isset($_POST['contenu']))
148 { 120 {
149 $Album->update($content); 121 $Album->update($content);
@@ -167,5 +139,15 @@ function submitCKeditor($nomFichier)
167 } 139 }
168} 140}
169 141
142// lien sans http://
143// un clic sur un lien dans l'éditeur affiche une infobulle montrant l'adresse cible du lien si celle-ci a déjà été précisée
144// il est possible de cliquer sur ce lien, ce qui ouvre un onglet avec le site demandé
145// toutefois si cette adresse est de type "domaine.fr" (sans http:// devant), le navigateur ne va pas rechercher un site mais un fichier comme si mon adresse était de type file:///fichier
146// tomber ainsi sur une page d'erreur est déroutant:
147// "ai-je perdu le texte que j'étais en train de taper?""
148// solution 1 (mauvaise): activer la redirection en cas d'erreur 404 dans le .htaccess
149// solution 2 (façon pop-up): fermer ce nouvel onglet avec echo '<SCRIPT>javascript:window.close()</SCRIPT>';
150// pour faire passer par le .htaccess l'info comme quoi la page précédente comportait un éditeur ouvert...
151
170function cleanHTML($contenu) 152function cleanHTML($contenu)
171{} 153{}
diff --git a/controller/visitor.php b/controller/visitor.php
index 239c139..a5bf538 100644
--- a/controller/visitor.php
+++ b/controller/visitor.php
@@ -51,49 +51,62 @@ function discoVisitor()
51 // modèle 51 // modèle
52 $AllAlbums = new Album($page_actuelle); 52 $AllAlbums = new Album($page_actuelle);
53 $AllAlbums->makeFileList(); 53 $AllAlbums->makeFileList();
54 $albumsJSON = array_reverse($AllAlbums->readAll()); // lourd
55 54
56 // $albums est un tableau de chaines JSON, 55 // contenu de tous les fichiers JSON (= tableau de chaines)
57 // chacune renferme 3 variables: titre, année, pochette 56 $albumsJSON = $AllAlbums->readAll();
57 // noms des fichiers JSON
58 $albumNamesJSON = $AllAlbums->getFileList();
58 59
59 // changer les chaines JSON en tableaux 60 // changer les chaines JSON en tableaux: titre, année, pochette
60 $i = 0; 61 $i = 0;
62 $annees = array();
61 foreach($albumsJSON as $oneAlbum) 63 foreach($albumsJSON as $oneAlbum)
62 { 64 {
63 $albumsJSON[$i] = json_decode($oneAlbum, true); 65 $albumsJSON[$i] = json_decode($oneAlbum, true);
66 $annees[$i] = $albumsJSON[$i][1];
67
68 // ajout des noms des fichiers JSON
69 $albumsJSON[$i][3] = $albumNamesJSON[$i];
70
64 $i++; 71 $i++;
65 } 72 }
73 // tri d'un tableau multidimensionnel
74 array_multisort($annees, $albumsJSON);
66 75
67 // on passe maintenant au contenu HTML 76 // on passe maintenant au contenu HTML
68 $albumNamesJSON = array_reverse($AllAlbums->getFileNames());
69 $AllAlbums->setFormat('html'); 77 $AllAlbums->setFormat('html');
70 $AllAlbums->makeFileList(); 78 $AllAlbums->makeFileList();
71 $albumNamesHTML = array_reverse($AllAlbums->getFileNames()); 79 $albumNamesHTML = $AllAlbums->getFileList();
72 80
73 // lien vers le HTML ou ancre? 81 // lien vers le HTML ou ancre?
74 // pour chaque album, détecter le fichier html 82 // pour chaque album, détecter le fichier html
75 // si non, ne fournir qu'un lien d'ancre pour la liste d'album 83 // si non, ne fournir qu'un lien d'ancre pour la liste d'album
76 $i = 0; 84 $i = 0;
77 $avecLien = []; 85 $avecLien = [];
78 foreach($albumNamesJSON as $oneAlbum) 86 $linkDiscoChrono = [];
87 foreach($albumsJSON as $oneAlbum)
79 { 88 {
80 // nom sans extension 89 // nom sans extension
81 $chemin = pathinfo($oneAlbum); 90 $chemin = pathinfo($oneAlbum[3]);
82 $nomJSONsansExt = $chemin['filename']; 91 $nomJSONsansExt = $chemin['filename'];
83 $chemin = pathinfo($albumNamesHTML[0]);
84 92
85 // détection 93 // au cas où la discographie ne contient aucun html
86 if(file_exists($chemin['dirname'] . '/' . $nomJSONsansExt . '.html')) 94 if(!empty($albumNamesHTML))
87 { 95 {
88 $lienAlbum[$i] = 'album&album_code=' . $nomJSONsansExt . '&album_name=' . $albumsJSON[$i][0]; 96 if(file_exists('data/discographie/html/' . $nomJSONsansExt . '.html'))
89 $avecLien[$i] = true; 97 {
98 $lienAlbum[$i] = 'album&album_code=' . $nomJSONsansExt . '&album_name=' . $albumsJSON[$i][0];
99 $avecLien[$i] = true;
100 $linkDiscoChrono[$i] = 'linkChrono'; // css
101 }
102 else
103 {
104 $lienAlbum[$i] = 'discographie#' . $albumsJSON[$i][0];
105 $avecLien[$i] = false;
106 $linkDiscoChrono[$i] = 'noLinkChrono'; // css
107 }
108 $i++;
90 } 109 }
91 else
92 {
93 $lienAlbum[$i] = 'discographie#' . $albumsJSON[$i][0];
94 $avecLien[$i] = false;
95 }
96 $i++;
97 } 110 }
98 111
99 // variables $css, $js et $content 112 // variables $css, $js et $content
@@ -102,6 +115,7 @@ function discoVisitor()
102 require('view/template.php'); 115 require('view/template.php');
103} 116}
104 117
118// page d'un album
105function album($albumCode, $albumName) 119function album($albumCode, $albumName)
106{ 120{
107 $page_actuelle = 'discographie'; 121 $page_actuelle = 'discographie';
diff --git a/imageAJAX.php b/imageAJAX.php
deleted file mode 100644
index 0831986..0000000
--- a/imageAJAX.php
+++ /dev/null
@@ -1,100 +0,0 @@
1<?php
2// imageAJAX.php
3//
4// le problème pour écrire ce fichier est qu'il est impossible d'afficher le contenu des variables avec "echo" ou "var_dump"
5// puisqu'on reste toujours sur la même page, il y a heureusement au moins deux manières de faire autrement:
6// - avec les outils de développement du navigateur (utiliser firefox ou chromium/chrome mais pas les autres)
7// - écrire les données dans un fichier de log
8
9// ce fichier est autonome vis-à-vis du reste du code PHP et sert uniquement à traiter les requêtes AJAX,
10// il reçoit un POST du "simple upload adapter", un plugin du ckeditor qui sert faire de l'AJAX
11// ce POST est une image et s'appelle 'upload', c'est à dire le tableau $_FILES['upload']
12// à la fin on retournera une chaine de caractères avec "echo" et au format json (parce que c'est ce que demande le client)
13
14// avec firefox, faire un clic droit dans la page et cliquer sur examiner l'élément, ou faire Ctrl + Maj + i
15// une fois dans les outils de dev, aller dans la section "Réseau", et ensuite essayer d'uploader un fichier
16// de nombreuses infos sur la dernière requête envoyée apparaissent:
17// fichier = imageAJAX.php
18// initiateur = ckeditor.js
19// état = code HTTP (200 = ok, 400 = erreur dans l'adresse du fichier .php, 500 = erreur interne au serveur)
20// méthode = POST
21// les onglets "En-têtes", "Requête" et "Réponse" donnent d'autres infos:
22// l'onglet "Requête" affiche name="upload",
23// l'onglet "Réponse" montre tout le tableau $_FILES si le PHP comporte l'instruction: $upload = var_dump($_FILES);
24
25// pour que le ckeditor arrête de renvoyer une erreur, j'ai donc dû:
26// - passer du code 500 au code 200, ce qui nécessite d'écrire quelque chose avec "echo", "var_dump", "print_r", etc
27// - et que la chaine écrite avec PHP soit au format json, ce qu'on obtient avec la fonction json_encode'
28
29// nous souhaitons bien sûr enregistrer le fichier et renvoyer une chaine json utilisable par le ckeditor
30// nous devons donc autoriser les bons dossiers en écriture, dont celui des fichiers temporaires du système d'exploitation
31// et renvoyer cette chaîne en json:
32//{
33// "url": "chemin/images/foo.jpg"
34//}
35
36// debuggage
37/*print_r($_FILES);
38$upload = array(
39 'name' => $_FILES['upload']['name'],
40 'type' => $_FILES['upload']['type'],
41 'tmp_name' => $_FILES['upload']['tmp_name'],
42 'error' => $_FILES['upload']['error'],
43 'size' => $_FILES['upload']['size']
44);
45print_r($upload);*/
46
47session_start();
48// et une backdoor de fermée!
49if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1 || !isset($_FILES['upload']) || empty($_FILES['upload']))
50{
51 header('Location: index.php?erreur=imageajax');
52}
53
54// get envoyé avec le javascript
55$page = $_GET['page'];
56
57// déjà fait dans installation.php
58if(!file_exists('data/' . $page . '/images'))
59{
60 mkdir('data/' . $page . '/images', 0777);
61 chmod('data/' . $page . '/images', 0777);
62}
63
64// taille en Mo à adapter au serveur (2Mo est la valeur par défaut dans le php.ini)
65$tailleMax = 2000000;
66$erreur = '';
67
68// traitement et enregistrement de l'image
69if (isset($_FILES['upload']) AND $_FILES['upload']['error'] == 0) // 0 signifie ok
70{
71 if ($_FILES['upload']['size'] <= $tailleMax )
72 {
73 $infos = pathinfo ($_FILES['upload']['name']);
74 $extension = $infos['extension'];
75 $extautorisées = array('jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff');
76 // on prend la même liste que celle côté javascript, le SVG est bloqué pour raison de sécurité (javascript à l'intérieur)
77 if (in_array ($extension, $extautorisées))
78 {
79 move_uploaded_file ($_FILES['upload']['tmp_name'], 'data/' . $page . '/images/' . $_FILES['upload']['name']);
80 chmod('data/' . $page . '/images/' . $_FILES['upload']['name'], 0666);
81 }
82 else{$erreur = 'mauvais format, veuillez utiliser une image comportant un de ces formats: jpg ou jpeg, png, gif, bmp, webp, tiff<br />le format svg n\'est pas supporté';}
83 }
84 else{$erreur = 'fichier trop lourd';}
85}
86else{$erreur = $_FILES['upload']['error'];}
87/* les erreurs retournées avec $_FILES['upload']['error']:
880 pas d'erreur
891 taille du fichier supérieure à la valeur de upload_max_filesize dans le fichier php.ini (par défaut = 2 MO)
902 taille du fichier supérieure à la valeur de MAX_FILE_SIZE dans le formulaire HTML
913 fichier partiellement téléchargé
924 pas de fichier du tout
936 pas de dossier temporaire pour mettre le fichier
947 echec de l'écriture sur le DD
958 envoi arrêté par une extension de PHP mais on ne nous dit pas pourquoi => diagnostic avec la fonction phpinfo() */
96
97// nouveau chemin à renvoyer en format json
98$chemin = '{"url": "data/' . $page . '/images/' . $_FILES['upload']['name'] . '"}';
99//echo json_encode($chemin);
100echo $chemin;
diff --git a/index.php b/index.php
index d8e0a58..7ffcad7 100644
--- a/index.php
+++ b/index.php
@@ -54,13 +54,31 @@ require('controller/password.php');
54installation(); 54installation();
55 55
56 56
57// traitement des requêtes AJAX
58if(isset($_GET['action']) && isset($_GET['page']) && $_GET['action'] == 'upload_image')
59{
60 // et une backdoor de fermée!
61 if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1 || !isset($_FILES['upload']) || empty($_FILES['upload']))
62 {
63 header('Location: index.php?erreur=image_ajax');
64 }
65 else
66 {
67 require('model/Image.php');
68 // paramètre "true" parce qu'on reçoit une requête AJAX
69 $Image = new Image(true);
70 $Image->upload();
71 }
72 exit; // arrêt ici !!
73}
74
57// traitement des POST du ckeditor 75// traitement des POST du ckeditor
58// la fonction submitCKeditor n'affiche rien (controller/admin.php n'est pas utilisé) puis redirige sans GET 76// la fonction submitCKeditor est "autonome", elle n'affiche rien puis redirige sans GET
59if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1 77if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1
60 && isset($_GET['action']) && $_GET['action'] == 'submit' 78 && isset($_GET['action']) && $_GET['action'] == 'submit'
61 // trois possibilités: on a un contenu HTML ou JSON ou les deux 79 // trois possibilités: on a un contenu HTML ou JSON ou les deux
62 && ((isset($_POST['contenu']) && $_POST['contenu'] != '') 80 && ((isset($_POST['contenu']) && $_POST['contenu'] != '')
63 || (isset($_POST['titre']) && isset($_POST['annee']) && isset($_POST['pochette'])))) 81 || (isset($_POST['titre']) && isset($_POST['annee']))))
64{ 82{
65 require('controller/ckeditor.php'); // traitement du POST 83 require('controller/ckeditor.php'); // traitement du POST
66 require('lib/htmlawed/htmLawed.php'); // failles XSS 84 require('lib/htmlawed/htmLawed.php'); // failles XSS
@@ -94,11 +112,7 @@ if(isset($_GET['action']) && isset($_GET['page']))
94 } 112 }
95} 113}
96 114
97// le site comporte deux modes: 115// contrôleur des pages en mode visiteur (= lecture uniquement)
98// le mode visiteur en "lecture seule" utilisant le contrôleur visitor.php
99// le mode admin avec droits en "écriture" utilisant le contrôleur admin.php
100
101// contrôleur des pages en mode visiteur
102// appelé tout le temps parce que certaines pages (accueil, menu) n'ont pas de version "admin" => à améliorer 116// appelé tout le temps parce que certaines pages (accueil, menu) n'ont pas de version "admin" => à améliorer
103require('controller/visitor.php'); 117require('controller/visitor.php');
104 118
@@ -111,6 +125,7 @@ if(isset($_GET['page']) && $_GET['page'] != 'menu')
111// contrôleur des pages en mode admin 125// contrôleur des pages en mode admin
112if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1) 126if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1)
113{ 127{
128 // contrôleur en mode admin (= lecture/écriture)
114 require('controller/admin.php'); 129 require('controller/admin.php');
115} 130}
116else 131else
diff --git a/model/Classes.php b/model/Classes.php
index 1846ce3..97a137a 100644
--- a/model/Classes.php
+++ b/model/Classes.php
@@ -31,7 +31,7 @@ class AllArticles
31 { 31 {
32 return($this->nbArticles); 32 return($this->nbArticles);
33 } 33 }
34 public function getFileNames() 34 public function getFileList()
35 { 35 {
36 return($this->files); 36 return($this->files);
37 } 37 }
@@ -154,21 +154,27 @@ class Album extends OneArticle
154{ 154{
155 // variables 155 // variables
156 //private $fileNameJSON; // même nom en .json 156 //private $fileNameJSON; // même nom en .json
157 //protected $format = 'json';
158 157
159 // GET 158 // GET
160 159
161 // SET 160 // SET
162 161
163 // fonctions CRUD 162 // fonctions CRUD
164
165 // create 163 // create
166 public function createVignette($titre, $annee, $pochette) 164 public function createVignette($titre, $annee, $pochette)
167 { 165 {
166 $this->format = 'json';
167
168 if($pochette != '') 168 if($pochette != '')
169 { 169 {
170 // enregistrer le fichier 170 // télécharger la pochette
171 // retourner une erreur en cas d'échec de l'upload 171 require('model/Image.php');
172 $Image = new Image(false);
173 $Image->upload();
174
175 /*$erreur = $Image->getError();
176 if(!empty($erreur))
177 {}*/
172 } 178 }
173 179
174 $albumJSON = json_encode([$titre, $annee, $pochette]); 180 $albumJSON = json_encode([$titre, $annee, $pochette]);
@@ -192,12 +198,4 @@ class Album extends OneArticle
192 // delete 198 // delete
193 public function delete() 199 public function delete()
194 {} 200 {}
195} 201} \ No newline at end of file
196
197
198
199// note: les pros font de l'hydration
200// le code du modèle est orienté objet et "refactorisé" d'une manière précise:
201// on utilise un objet pour une chose (des articles, commentaires, etc),
202// un objet article contiendrait ainsi tout le nécessaire pour lire, écrire ou modifier un article
203// il y a pour ça un programme appelé "doctrine" (inclu dans symphony) qui est capable de lire une base de données et d'en écrire les objets PHP \ No newline at end of file
diff --git a/model/Image.php b/model/Image.php
new file mode 100644
index 0000000..0070b70
--- /dev/null
+++ b/model/Image.php
@@ -0,0 +1,59 @@
1<?php
2// model/Image.php
3
4class Image
5{
6 private const MAX_WEIGHT = 2000000; // taille max des images (par défaut 2Mo dans php.ini)
7 private $page;
8 private $ajax = false;
9 private $erreur = '';
10
11 public function __construct($ajax)
12 {
13 // get envoyé avec le javascript
14 $this->page = $_GET['page'];
15 $this->ajax = $ajax;
16 }
17
18 // GET
19 public function getError()
20 {
21 return($this->erreur);
22 }
23
24 public function upload()
25 {
26
27 // traitement et enregistrement de l'image
28 if (isset($_FILES['upload']) AND $_FILES['upload']['error'] == 0) // 0 signifie ok
29 {
30 if ($_FILES['upload']['size'] <= self::MAX_WEIGHT)
31 {
32 $infos = pathinfo($_FILES['upload']['name']);
33 $extension = $infos['extension'];
34 $extautorisées = array('jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff');
35 // on prend la même liste que celle côté javascript, le SVG est bloqué pour raison de sécurité (javascript à l'intérieur)
36 if (in_array($extension, $extautorisées))
37 {
38 move_uploaded_file($_FILES['upload']['tmp_name'], 'data/' . $this->page . '/images/' . $_FILES['upload']['name']);
39 chmod('data/' . $this->page . '/images/' . $_FILES['upload']['name'], 0666);
40 }
41 else{$this->erreur = 'mauvais format, veuillez utiliser une image comportant un de ces formats: jpg ou jpeg, png, gif, bmp, webp, tiff<br />le format svg n\'est pas supporté';}
42 }
43 else{$this->erreur = 'fichier trop lourd';}
44 }
45 else
46 {
47 $this->erreur = $_FILES['upload']['error'];
48 }
49
50 // retour des rêquetes AJAX
51 if($this->ajax)
52 {
53 // nouveau chemin à renvoyer en format json
54 $chemin = '{"url": "data/' . $this->page . '/images/' . $_FILES['upload']['name'] . '"}';
55 //echo json_encode($chemin);
56 echo $chemin;
57 }
58 }
59} \ No newline at end of file
diff --git a/public/discographie.css b/public/discographie.css
index adf5ac0..8b050db 100644
--- a/public/discographie.css
+++ b/public/discographie.css
@@ -39,7 +39,8 @@ aside div
39 /*padding: 5px;*/ 39 /*padding: 5px;*/
40 display: none; 40 display: none;
41 z-index: 1; /* placer le menu déroulant au dessus */ 41 z-index: 1; /* placer le menu déroulant au dessus */
42 background-color: #9fa8d0; 42 /*background-color: #9fa8d0;*/
43 background-color: #a4afd4;
43} 44}
44 45
45#chronologie p 46#chronologie p
@@ -47,6 +48,29 @@ aside div
47 margin: 8px; 48 margin: 8px;
48} 49}
49 50
51#chronologie p a:visited
52{
53 color: blue;
54}
55#chronologie p a:hover
56{
57 color: black;
58}
59
60.linkChrono
61{
62 text-decoration: none;
63}
64.linkChrono:hover
65{
66 text-decoration: underline;
67}
68.noLinkChrono
69{
70 text-decoration: none;
71 color: black;
72}
73
50/* PC uniquement, pour les smartphones prévoir un clic 74/* PC uniquement, pour les smartphones prévoir un clic
51=> :checked et une checkbox 75=> :checked et une checkbox
52=> ou la balise select qui crée un menu déroulant */ 76=> ou la balise select qui crée un menu déroulant */
@@ -129,11 +153,17 @@ a:hover figure figcaption
129 text-decoration: underline; 153 text-decoration: underline;
130} 154}
131 155
156
132/* page dédiée à un album */ 157/* page dédiée à un album */
133#albumHTML 158#albumHTML
134{ 159{
135 width: 100%; 160 width: 100%;
136} 161}
162.linkAlbumHTML
163{
164 color: blue;
165}
166
137 167
138@media screen and (min-width: 700px) 168@media screen and (min-width: 700px)
139{ 169{
diff --git a/public/donnees_hors_editeur.css b/public/donnees_hors_editeur.css
index 8619938..fdb12b5 100644
--- a/public/donnees_hors_editeur.css
+++ b/public/donnees_hors_editeur.css
@@ -26,13 +26,13 @@ input[type="checkbox"]:checked{border: none; background: #26ab33;}
26.table td{border: 1px grey solid; padding: 7px; min-width: 30px;} 26.table td{border: 1px grey solid; padding: 7px; min-width: 30px;}
27td p{margin: 0px;} 27td p{margin: 0px;}
28 28
29.image{margin: 0px 0px 0px 5px; text-align: center; display: inline-block;} 29.image{margin: 0px; text-align: center; display: inline-block;}
30.image img{max-width: 630px;} 30.image img{max-width: 630px;}
31.image-style-side{float: right;} 31.image-style-side{float: right;}
32.image-style-side img{max-width: 315px;} 32.image-style-side img{max-width: 315px;}
33.image>figcaption{padding: 7px; text-align: center; font-size: small; background-color: #f0f0f0;} 33.image>figcaption{padding: 7px; text-align: center; font-size: small; background-color: #f0f0f0;}
34 34
35.boutonArticle{clear: both;} 35.boutonArticle{clear: both; padding: 10px 0px;}
36article:after{content: ""; display: block; clear: both;} 36article:after{content: ""; display: block; clear: both;}
37 37
38iframe{min-width: 400px; min-height: 300px; max-width: 1200px; max-height: 900px;} \ No newline at end of file 38iframe{min-width: 400px; min-height: 300px; max-width: 1200px; max-height: 900px;} \ No newline at end of file
diff --git a/public/melaine.css b/public/melaine.css
index 9736147..f7faf99 100644
--- a/public/melaine.css
+++ b/public/melaine.css
@@ -22,7 +22,6 @@ figure
22} 22}
23.boutonArticle 23.boutonArticle
24{ 24{
25 padding-bottom: 20px;
26 border-bottom: 1px black solid; 25 border-bottom: 1px black solid;
27} 26}
28.boutonArticle a 27.boutonArticle a
diff --git a/view/album.php b/view/album.php
index 39d180a..921efaf 100644
--- a/view/album.php
+++ b/view/album.php
@@ -30,6 +30,6 @@ ob_start();
30 <?= $album ?> 30 <?= $album ?>
31 </article> 31 </article>
32 32
33 <p><a href="index.php?page=discographie" >Retour à la discographie</a></p> 33 <p><a class="linkAlbumHTML" href="index.php?page=discographie" >Retour à la discographie</a></p>
34<?php 34<?php
35$content = ob_get_clean(); 35$content = ob_get_clean();
diff --git a/view/discographie.php b/view/discographie.php
index fcb788f..19e982b 100644
--- a/view/discographie.php
+++ b/view/discographie.php
@@ -55,7 +55,7 @@ foreach($albumsJSON as $oneAlbum)
55 // mettre une adresse lorsqu'un fichier html existe 55 // mettre une adresse lorsqu'un fichier html existe
56 // si il n'existe pas, mettre une ancre vers l'endroit sur la page 56 // si il n'existe pas, mettre une ancre vers l'endroit sur la page
57?> 57?>
58 <p><a href="index.php?page=<?= $lienAlbum[$i] ?>" ><?= $oneAlbum[1] ?>: <?= $oneAlbum[0] ?></a></p> 58 <p><a class="<?= $linkDiscoChrono[$i] ?>" href="index.php?page=<?= $lienAlbum[$i] ?>" ><?= $oneAlbum[1] ?> <?= $oneAlbum[0] ?></a></p>
59<?php 59<?php
60 $i++; 60 $i++;
61} 61}
@@ -106,8 +106,6 @@ foreach($albumsJSON as $oneAlbum)
106<?php 106<?php
107 } 107 }
108?> 108?>
109
110
111 <figure> 109 <figure>
112 <img class="vignette" src="data/discographie/images/<?= $oneAlbum[2] ?>" alt="" > 110 <img class="vignette" src="data/discographie/images/<?= $oneAlbum[2] ?>" alt="" >
113 <figcaption><?= $oneAlbum[0] ?><br><?= $oneAlbum[1] ?></figcaption> 111 <figcaption><?= $oneAlbum[0] ?><br><?= $oneAlbum[1] ?></figcaption>
diff --git a/view/template-formulaires.php b/view/template-formulaires.php
index 7eb1bb5..391f729 100644
--- a/view/template-formulaires.php
+++ b/view/template-formulaires.php
@@ -24,9 +24,9 @@ ob_start();
24 <label for="titre" >Titre</label> 24 <label for="titre" >Titre</label>
25 <input type="text" name="titre" required ><br /> 25 <input type="text" name="titre" required ><br />
26 <label for="annee" >Année</label> 26 <label for="annee" >Année</label>
27 <input type="text" name="annee" ><br /> 27 <input type="text" name="annee" required ><br />
28 <label for="pochette" >Pochette du disque (jpg ou png)</label> 28 <label for="pochette" >Pochette du disque (jpg ou png)</label>
29 <input type="file" name="pochette" > 29 <input type="file" name="upload" >
30 <br /><br /> 30 <br /><br />
31<?php 31<?php
32$inputsAlbum = ob_get_clean(); 32$inputsAlbum = ob_get_clean();
@@ -37,7 +37,7 @@ ob_start();
37?> 37?>
38 38
39 <div class="conteneur_article" > 39 <div class="conteneur_article" >
40 <form action="index.php?page=<?= $page_actuelle ?>&article=<?= $numArticle ?>&action=submit" method="post" > 40 <form action="index.php?page=<?= $page_actuelle ?>&article=<?= $numArticle ?>&action=submit" method="post" enctype="multipart/form-data" >
41<?php 41<?php
42if($page_actuelle == 'discographie') 42if($page_actuelle == 'discographie')
43{ 43{
@@ -154,13 +154,12 @@ if($page_actuelle == 'discographie')
154 // "url": "https://example.com/images/foo.jpg" 154 // "url": "https://example.com/images/foo.jpg"
155 //} 155 //}
156 // cette url sert à deux choses: 156 // cette url sert à deux choses:
157 // - à télécharger l'image avant de la placer dans l'éditeur 157 // - à télécharger immédiatement l'image envoyée pour la placer dans l'éditeur
158 // - écrire le HTML qu'on enregistrera ensuite 158 // - à inclure l'adresse de l'image dans le HTML produit par l'éditeur
159 // en effet, le fichier est téléchargé sur le serveur avant de revenir dans l'éditeur comme un téléchargement classique
160 simpleUpload: { 159 simpleUpload: {
161 uploadUrl: 'imageAJAX.php?page=<?= $page_actuelle ?>', 160 uploadUrl: 'index.php?action=upload_image&page=<?= $page_actuelle ?>',
162 // noter qu'il est possible (parce que souhaitable je ne pense pas) d'envoyer une requête AJAX 161 // noter qu'il est possible (parce que souhaitable je ne pense pas) d'envoyer une requête AJAX
163 // en indiquant une adresse "statique" du type: fichier.txt ou .xml, jpg, png, etc 162 // en indiquant une adresse "statique" du type: fichier.txt ou .xml, jpg, png, etc,
164 163
165 // Headers supplémentaires envoyés avec la requête 164 // Headers supplémentaires envoyés avec la requête
166 // c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF 165 // c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF
@@ -171,11 +170,8 @@ if($page_actuelle == 'discographie')
171 }, 170 },
172 // formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff 171 // formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff
173 // le svg n'est pas dans la liste, pour raison de sécurité apparemment, il parait qu'on peut mettre du javascript à l'intérieur 172 // le svg n'est pas dans la liste, pour raison de sécurité apparemment, il parait qu'on peut mettre du javascript à l'intérieur
174 173 // ce plugin est simple (JS pur) et n'oblige pas le serveur à disposer de l'extension GD
175 // ce plugin a l'intérêt de ne pas imposer l'utilisation de l'extension GD de PHP, 174 // niveau perfs, on garde le choix d'utiler GD ou imagemagick ou un système d'onglets
176 // Reste qu'il sera quand même intéressant de l'ajouter pour le redimensionnement des images trop lourdes,
177 // quoi que le système d'onglets (limiter l'affichge à 5 ou 10 articles par page) règle aussi le problème d'une autre manière
178
179 175
180 // plugin autosave 176 // plugin autosave
181 } ) 177 } )