diff options
author | polo <ordipolo@gmx.fr> | 2025-04-06 12:18:49 +0200 |
---|---|---|
committer | polo <ordipolo@gmx.fr> | 2025-04-06 12:18:49 +0200 |
commit | 68b6058e2a27fc251c117c4efeb141392a0c9736 (patch) | |
tree | 5c029b2c147bd14f777765d41bc623582c81daa2 | |
parent | e4a325c9d5c07f09bc18b7e366ffb82b82c43502 (diff) | |
download | cms-68b6058e2a27fc251c117c4efeb141392a0c9736.zip |
nouvel article, boutons dans les builders, makeArticleNode, JS MAJ page, tri quand déplacement ou suppression
28 files changed, 479 insertions, 159 deletions
diff --git a/public/css/main.css b/public/css/main.css index 50c2173..cb44e16 100644 --- a/public/css/main.css +++ b/public/css/main.css | |||
@@ -28,8 +28,8 @@ section > p /* boutons spéciaux mode admin */ | |||
28 | } | 28 | } |
29 | .galery_photos .html_from_editor img | 29 | .galery_photos .html_from_editor img |
30 | { | 30 | { |
31 | max-width: 400px; | 31 | max-width: 300px; |
32 | max-height: 250px; | 32 | max-height: 200px; |
33 | } | 33 | } |
34 | article | 34 | article |
35 | { | 35 | { |
@@ -50,6 +50,11 @@ article .logo2 | |||
50 | { | 50 | { |
51 | width: 100%; | 51 | width: 100%; |
52 | } | 52 | } |
53 | article img | ||
54 | { | ||
55 | max-width: 100%; | ||
56 | height: auto; | ||
57 | } | ||
53 | .new_content_text | 58 | .new_content_text |
54 | { | 59 | { |
55 | max-height: 250px; | 60 | max-height: 250px; |
@@ -120,4 +125,9 @@ main button:hover | |||
120 | cursor: pointer; /* curseur qui pointe du doigt */ | 125 | cursor: pointer; /* curseur qui pointe du doigt */ |
121 | background-color: #ffff00; | 126 | background-color: #ffff00; |
122 | border-radius: 4px; | 127 | border-radius: 4px; |
128 | } | ||
129 | |||
130 | article a:hover | ||
131 | { | ||
132 | cursor: pointer; | ||
123 | } \ No newline at end of file | 133 | } \ No newline at end of file |
diff --git a/public/css/trombinoscope.css b/public/css/trombinoscope.css index f42dad8..357e6b0 100644 --- a/public/css/trombinoscope.css +++ b/public/css/trombinoscope.css | |||
@@ -1,4 +1,10 @@ | |||
1 | article img | 1 | article img |
2 | { | 2 | { |
3 | border-radius: 50%; | 3 | border-radius: 50%; |
4 | } | ||
5 | |||
6 | .grid_columns | ||
7 | { | ||
8 | /* écrase les 3 colonnes par défaut */ | ||
9 | grid-template-columns: repeat(4, 1fr); | ||
4 | } \ No newline at end of file | 10 | } \ No newline at end of file |
diff --git a/public/images/SAR_Constructions.jpg b/public/images/SAR_Constructions.jpg new file mode 100644 index 0000000..1b9cb81 --- /dev/null +++ b/public/images/SAR_Constructions.jpg | |||
Binary files differ | |||
diff --git a/public/images/Ysoline Rabin.jpg b/public/images/Ysoline Rabin.jpg new file mode 100644 index 0000000..2ecfcc4 --- /dev/null +++ b/public/images/Ysoline Rabin.jpg | |||
Binary files differ | |||
diff --git a/public/images/beatrice_carre.jpg b/public/images/beatrice_carre.jpg new file mode 100644 index 0000000..8db4036 --- /dev/null +++ b/public/images/beatrice_carre.jpg | |||
Binary files differ | |||
diff --git a/public/images/eaulibre.jpg b/public/images/eaulibre.jpg new file mode 100644 index 0000000..02b1917 --- /dev/null +++ b/public/images/eaulibre.jpg | |||
Binary files differ | |||
diff --git a/public/images/frank_pouliquen.jpg b/public/images/frank_pouliquen.jpg new file mode 100644 index 0000000..7bb3ead --- /dev/null +++ b/public/images/frank_pouliquen.jpg | |||
Binary files differ | |||
diff --git a/public/images/leclerc_bigouden.png b/public/images/leclerc_bigouden.png new file mode 100644 index 0000000..596ead7 --- /dev/null +++ b/public/images/leclerc_bigouden.png | |||
Binary files differ | |||
diff --git a/public/images/silhouette nageur.jpg b/public/images/silhouette nageur.jpg new file mode 100644 index 0000000..526cc0f --- /dev/null +++ b/public/images/silhouette nageur.jpg | |||
Binary files differ | |||
diff --git a/public/images/silhouette nageuse.jpg b/public/images/silhouette nageuse.jpg new file mode 100644 index 0000000..e4f7307 --- /dev/null +++ b/public/images/silhouette nageuse.jpg | |||
Binary files differ | |||
diff --git a/public/images/yves_pouliquen.jpg b/public/images/yves_pouliquen.jpg new file mode 100644 index 0000000..435c69e --- /dev/null +++ b/public/images/yves_pouliquen.jpg | |||
Binary files differ | |||
diff --git a/public/index.php b/public/index.php index 3c6f261..2512d6d 100644 --- a/public/index.php +++ b/public/index.php | |||
@@ -69,9 +69,9 @@ elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp') | |||
69 | } | 69 | } |
70 | 70 | ||
71 | // -- contrôleurs -- | 71 | // -- contrôleurs -- |
72 | $director = new Director($entityManager); | 72 | $director = new Director($entityManager, true); |
73 | $director->makeRootNode($id); | 73 | $director->makeRootNode($id); |
74 | $node = $director->getRootNode(); | 74 | $node = $director->getNode(); |
75 | 75 | ||
76 | // -- vues -- | 76 | // -- vues -- |
77 | $view_builder = new ViewBuilder($node); | 77 | $view_builder = new ViewBuilder($node); |
diff --git a/public/js/main.js b/public/js/main.js index 1351fea..c05eb2f 100644 --- a/public/js/main.js +++ b/public/js/main.js | |||
@@ -30,10 +30,10 @@ function copyInClipBoard(link){ | |||
30 | } | 30 | } |
31 | 31 | ||
32 | // complète les fonctions dans tinymce.js | 32 | // complète les fonctions dans tinymce.js |
33 | function switchPositions(articleId, direction) | 33 | function switchPositions(article_id, direction) |
34 | { | 34 | { |
35 | const current_article = document.getElementById(articleId).parentElement.parentElement; | 35 | const current_article = findParent(document.getElementById(article_id), 'article'); |
36 | var other_article = current_article; | 36 | var other_article; |
37 | 37 | ||
38 | if(direction == 'down'){ | 38 | if(direction == 'down'){ |
39 | other_article = current_article.nextElementSibling; | 39 | other_article = current_article.nextElementSibling; |
@@ -41,14 +41,23 @@ function switchPositions(articleId, direction) | |||
41 | else if(direction == 'up'){ | 41 | else if(direction == 'up'){ |
42 | other_article = current_article.previousElementSibling; | 42 | other_article = current_article.previousElementSibling; |
43 | } | 43 | } |
44 | const other_article_id = other_article.querySelector('div[id]').id; | 44 | |
45 | var other_article_id; | ||
46 | try{ | ||
47 | other_article_id = other_article.querySelector('div[id]').id; | ||
48 | other_article_id = 'i' + other_article_id.slice(1); // peut mieux faire | ||
49 | } | ||
50 | catch(error){ | ||
51 | console.log('Inversion impossible'); | ||
52 | return; | ||
53 | } | ||
45 | 54 | ||
46 | fetch('index.php?action=switch_positions', { | 55 | fetch('index.php?action=switch_positions', { |
47 | method: 'POST', | 56 | method: 'POST', |
48 | headers: { | 57 | headers: { |
49 | 'Content-Type': 'application/json' | 58 | 'Content-Type': 'application/json' |
50 | }, | 59 | }, |
51 | body: JSON.stringify({ id1: articleId, id2: other_article_id }) | 60 | body: JSON.stringify({ id1: article_id, id2: other_article_id }) |
52 | }) | 61 | }) |
53 | .then(response => response.json()) | 62 | .then(response => response.json()) |
54 | .then(data => { | 63 | .then(data => { |
@@ -155,4 +164,15 @@ function submitDate(id_date) | |||
155 | .catch(error => { | 164 | .catch(error => { |
156 | console.error('Erreur:', error); | 165 | console.error('Erreur:', error); |
157 | }); | 166 | }); |
167 | } | ||
168 | |||
169 | function findParent(element, tag_name) { | ||
170 | while (element !== null) { | ||
171 | if (element.tagName === tag_name.toUpperCase()) // tagName est en majuscules | ||
172 | { | ||
173 | return element; | ||
174 | } | ||
175 | element = element.parentElement; | ||
176 | } | ||
177 | return null; | ||
158 | } \ No newline at end of file | 178 | } \ No newline at end of file |
diff --git a/public/js/tinymce.js b/public/js/tinymce.js index d3c9739..cb1938a 100644 --- a/public/js/tinymce.js +++ b/public/js/tinymce.js | |||
@@ -1,15 +1,26 @@ | |||
1 | let editors = {}; | 1 | let editors = {}; |
2 | 2 | ||
3 | function openEditor(id, page = '') { | 3 | function openEditor(id, page = '') { |
4 | const real_id = 'i' + id.slice(1); | 4 | var creation_mode; |
5 | var real_id; | ||
6 | var article; | ||
5 | 7 | ||
6 | // Récupérer et sauvegarder le contenu d'origine de l'article | 8 | // création ou modification d'un article? |
7 | const articleContent = document.getElementById(id).innerHTML; | 9 | if(id[0] === 'n'){ |
8 | document.getElementById(id).setAttribute('data-original-content', articleContent); | 10 | creation_mode = true; |
11 | article = document.getElementById(id); | ||
12 | } | ||
13 | else{ | ||
14 | creation_mode = false; | ||
15 | // Récupérer et sauvegarder le contenu d'origine de l'article | ||
16 | real_id = 'i' + id.slice(1); | ||
17 | article = document.getElementById(id); | ||
18 | document.getElementById(id).setAttribute('data-original-content', article.innerHTML); | ||
19 | } | ||
9 | 20 | ||
10 | tinymce.init({ | 21 | tinymce.init({ |
11 | selector: `#${id}`, | 22 | selector: `#${id}`, |
12 | language: 'fr_FR', // télécharger des paquets de langue ici: https://www.tiny.cloud/get-tiny/language-packages/ | 23 | language: 'fr_FR', // téléchargement ici: https://www.tiny.cloud/get-tiny/language-packages/ |
13 | language_url: 'js/tinymce-langs/fr_FR.js', // ou installer tweeb/tinymce-i18n avec composer | 24 | language_url: 'js/tinymce-langs/fr_FR.js', // ou installer tweeb/tinymce-i18n avec composer |
14 | license_key: 'gpl', | 25 | license_key: 'gpl', |
15 | branding: false, | 26 | branding: false, |
@@ -23,14 +34,18 @@ function openEditor(id, page = '') { | |||
23 | editors[id] = editor; | 34 | editors[id] = editor; |
24 | 35 | ||
25 | // boutons "Modifier", "Supprimer", "déplacer vers le haut", "déplacer vers le bas", "Annuler" et "Soumettre" | 36 | // boutons "Modifier", "Supprimer", "déplacer vers le haut", "déplacer vers le bas", "Annuler" et "Soumettre" |
26 | document.querySelector(`#edit-${id}`).classList.add('hidden'); | ||
27 | document.querySelector(`#cancel-${id}`).classList.remove('hidden'); | 37 | document.querySelector(`#cancel-${id}`).classList.remove('hidden'); |
28 | document.querySelector(`#submit-${id}`).classList.remove('hidden'); | 38 | document.querySelector(`#submit-${id}`).classList.remove('hidden'); |
29 | document.querySelector(`#delete-${real_id}`).classList.add('hidden'); | 39 | if(creation_mode === false){ |
30 | // boutons absents page article | 40 | document.querySelector(`#edit-${id}`).classList.add('hidden'); |
31 | if(page != 'article'){ | 41 | document.querySelector(`#delete-${real_id}`).classList.add('hidden'); |
32 | document.querySelector(`#position_up-${id}`).classList.add('hidden'); | 42 | if(page != 'article'){ |
33 | document.querySelector(`#position_down-${id}`).classList.add('hidden'); | 43 | document.querySelector(`#position_up-${id}`).classList.add('hidden'); |
44 | document.querySelector(`#position_down-${id}`).classList.add('hidden'); | ||
45 | } | ||
46 | } | ||
47 | else{ | ||
48 | document.querySelector(`#new-${id}`).classList.add('hidden'); // id = new-new-id_node | ||
34 | } | 49 | } |
35 | }); | 50 | }); |
36 | }, | 51 | }, |
@@ -60,7 +75,9 @@ function openEditor(id, page = '') { | |||
60 | }); | 75 | }); |
61 | 76 | ||
62 | // Remplacer le contenu de l'article par l'éditeur | 77 | // Remplacer le contenu de l'article par l'éditeur |
63 | document.getElementById(id).innerHTML = articleContent; | 78 | if(creation_mode === false){ |
79 | document.getElementById(id).innerHTML = article.innerHTML; | ||
80 | } | ||
64 | } | 81 | } |
65 | 82 | ||
66 | function deleteArticle(id, page = '') { | 83 | function deleteArticle(id, page = '') { |
@@ -100,33 +117,78 @@ function deleteArticle(id, page = '') { | |||
100 | } | 117 | } |
101 | } | 118 | } |
102 | 119 | ||
103 | function closeEditor(id, page = '', display_old = true) | 120 | function closeEditor(id, page = '', restore_old = true) |
104 | { | 121 | { |
105 | const real_id = 'i' + id.slice(1); | 122 | var creation_mode; |
123 | var real_id; | ||
124 | var article; | ||
125 | var parent; | ||
126 | |||
127 | // création ou modification d'un article? | ||
128 | if(id[0] === 'n'){ | ||
129 | creation_mode = true; | ||
130 | } | ||
131 | else{ | ||
132 | creation_mode = false; | ||
133 | } | ||
106 | 134 | ||
107 | // Fermer l'éditeur | 135 | // Fermer l'éditeur |
108 | tinymce.remove(`#${id}`); | 136 | tinymce.remove(`#${id}`); |
109 | delete editors[id]; | 137 | delete editors[id]; |
110 | 138 | ||
139 | if(creation_mode){ | ||
140 | article = document.getElementById(id); | ||
141 | parent = findParent(article, 'section'); | ||
142 | } | ||
143 | else{ | ||
144 | real_id = 'i' + id.slice(1); | ||
145 | } | ||
146 | |||
111 | // Restaurer le contenu d'origine de l'article | 147 | // Restaurer le contenu d'origine de l'article |
112 | if(display_old){ | 148 | if(restore_old){ |
113 | const originalContent = document.getElementById(id).getAttribute('data-original-content'); | 149 | const originalContent = document.getElementById(id).getAttribute('data-original-content'); |
114 | document.getElementById(id).innerHTML = originalContent; | 150 | document.getElementById(id).innerHTML = originalContent; |
115 | } | 151 | } |
116 | 152 | ||
117 | // boutons "Modifier", "Supprimer", "déplacer vers le haut", "déplacer vers le bas", "Annuler" et "Soumettre" | 153 | // boutons: "Nouvel article", Modifier", "Supprimer", "déplacer vers le haut", "déplacer vers le bas", "Annuler" et "Valider" |
118 | document.querySelector(`#edit-${id}`).classList.remove('hidden'); | ||
119 | document.querySelector(`#cancel-${id}`).classList.add('hidden'); | 154 | document.querySelector(`#cancel-${id}`).classList.add('hidden'); |
120 | document.querySelector(`#submit-${id}`).classList.add('hidden'); | 155 | document.querySelector(`#submit-${id}`).classList.add('hidden'); |
121 | document.querySelector(`#delete-${real_id}`).classList.remove('hidden'); | 156 | if(creation_mode){ |
122 | // boutons absents page article | 157 | document.querySelector(`#new-${id}`).classList.remove('hidden'); // id = new-new-id_node |
158 | } | ||
159 | else{ | ||
160 | document.querySelector(`#edit-${id}`).classList.remove('hidden'); | ||
161 | if(page != 'article'){ | ||
162 | document.querySelector(`#position_up-${id}`).classList.remove('hidden'); | ||
163 | document.querySelector(`#position_down-${id}`).classList.remove('hidden'); | ||
164 | document.querySelector(`#delete-${id}`).classList.remove('hidden'); | ||
165 | } | ||
166 | } | ||
123 | if(page != 'article'){ | 167 | if(page != 'article'){ |
124 | document.querySelector(`#position_up-${id}`).classList.remove('hidden'); | 168 | /*document.querySelector(`#position_up-${id}`).classList.remove('hidden'); |
125 | document.querySelector(`#position_down-${id}`).classList.remove('hidden'); | 169 | document.querySelector(`#position_down-${id}`).classList.remove('hidden'); |
126 | } | 170 | document.querySelector(`#delete-${id}`).classList.remove('hidden');*/ |
171 | } | ||
172 | else{ | ||
173 | //document.querySelector(`#delete-${real_id}`).classList.remove('hidden'); | ||
174 | } | ||
175 | |||
127 | } | 176 | } |
128 | 177 | ||
129 | function submitArticle(id, page = '') { | 178 | function submitArticle(id, page = '', clone = null) { |
179 | //var creation_mode; | ||
180 | if(id[0] === 'n'){ | ||
181 | //creation_mode = true; | ||
182 | |||
183 | // sécurité | ||
184 | if(clone == null){ | ||
185 | return; | ||
186 | } | ||
187 | } | ||
188 | else{ | ||
189 | //creation_mode = false; | ||
190 | } | ||
191 | |||
130 | // Récupérer l'éditeur correspondant à l'article | 192 | // Récupérer l'éditeur correspondant à l'article |
131 | const editor = editors[id]; | 193 | const editor = editors[id]; |
132 | if(!editor) { | 194 | if(!editor) { |
@@ -150,7 +212,50 @@ function submitArticle(id, page = '') { | |||
150 | if (data.success) { | 212 | if (data.success) { |
151 | // Fermer l'éditeur et mettre à jour le contenu de l'article | 213 | // Fermer l'éditeur et mettre à jour le contenu de l'article |
152 | closeEditor(id, page, false); | 214 | closeEditor(id, page, false); |
153 | document.getElementById(id).innerHTML = html; | 215 | if(id[0] === 'n'){ |
216 | var share_btn = document.querySelector(`.share.hidden`); // combinaison de deux classes | ||
217 | var new_btn = document.querySelector(`#new-${id}`); | ||
218 | var edit_btn = document.querySelector(`#edit-${id}`); | ||
219 | var pos_up_btn = document.querySelector(`#position_up-${id}`); | ||
220 | var pos_down_btn = document.querySelector(`#position_down-${id}`); | ||
221 | var delete_btn = document.querySelector(`#delete-${id}`); | ||
222 | var cancel_btn = document.querySelector(`#cancel-${id}`); | ||
223 | var submit_btn = document.querySelector(`#submit-${id}`); | ||
224 | |||
225 | share_btn.classList.remove('hidden') | ||
226 | new_btn.classList.add('hidden'); | ||
227 | edit_btn.classList.remove('hidden'); | ||
228 | pos_up_btn.classList.remove('hidden'); | ||
229 | pos_down_btn.classList.remove('hidden'); | ||
230 | delete_btn.classList.remove('hidden'); | ||
231 | //cancel_btn.classList.add('hidden'); | ||
232 | //submit_btn.classList.add('hidden'); | ||
233 | |||
234 | var article = document.getElementById(id); | ||
235 | var parent = findParent(article, 'article'); | ||
236 | //share_btn.setAttribute('href', '#' + data.article_id); | ||
237 | share_btn.setAttribute('onclick', "copyInClipBoard('" + window.location.href + data.article_id + "')"); // # de l'ancre ajouté au clic sur le lien ouvrant l'éditeur | ||
238 | article.id = data.article_id; | ||
239 | edit_btn.id = 'edit-' + data.article_id; | ||
240 | edit_btn.querySelector('.action_icon').setAttribute('onclick', "openEditor('" + data.article_id + "')"); | ||
241 | pos_up_btn.id = 'position_up-' + data.article_id; | ||
242 | pos_up_btn.querySelector('.action_icon').setAttribute('onclick', "switchPositions('" + data.article_id + "', 'up')"); | ||
243 | pos_down_btn.id = 'position_down-' + data.article_id; | ||
244 | pos_down_btn.querySelector('.action_icon').setAttribute('onclick', "switchPositions('" + data.article_id + "', 'down')"); | ||
245 | delete_btn.id = 'delete-' + data.article_id; | ||
246 | delete_btn.querySelector('.action_icon').setAttribute('onclick', "deleteArticle('" + data.article_id + "')"); | ||
247 | cancel_btn.id = 'cancel-' + data.article_id; | ||
248 | cancel_btn.querySelector('button').setAttribute('onclick', "closeEditor('" + data.article_id + "')"); | ||
249 | submit_btn.id = 'submit-' + data.article_id; | ||
250 | submit_btn.querySelector('button').setAttribute('onclick', "submitArticle('" + data.article_id + "')"); | ||
251 | |||
252 | var next_div = parent.nextElementSibling.nextElementSibling; | ||
253 | parent.parentNode.replaceChild(clone, parent); | ||
254 | next_div.appendChild(parent); | ||
255 | } | ||
256 | else{ | ||
257 | //document.getElementById(id).innerHTML = html; | ||
258 | } | ||
154 | } | 259 | } |
155 | else { | 260 | else { |
156 | alert('Erreur lors de la sauvegarde de l\'article.'); | 261 | alert('Erreur lors de la sauvegarde de l\'article.'); |
diff --git a/src/controller/Director.php b/src/controller/Director.php index 5ff8f47..db84661 100644 --- a/src/controller/Director.php +++ b/src/controller/Director.php | |||
@@ -13,17 +13,29 @@ class Director | |||
13 | static public Menu $menu_data; // pour NavBuilder | 13 | static public Menu $menu_data; // pour NavBuilder |
14 | static public Path $page_path; // pour BreadcrumbBuilder | 14 | static public Path $page_path; // pour BreadcrumbBuilder |
15 | private Page $page; | 15 | private Page $page; |
16 | private Node $root_node; | 16 | private Node $node; |
17 | private Node $article; | ||
17 | 18 | ||
18 | public function __construct(EntityManager $entityManager) | 19 | public function __construct(EntityManager $entityManager, bool $for_display = false) |
19 | { | 20 | { |
20 | $this->entityManager = $entityManager; | 21 | $this->entityManager = $entityManager; |
21 | self::$menu_data = new Menu($entityManager); // Menu est un modèle mais pas une entité | 22 | if($for_display){ |
22 | self::$page_path = new Path(); | 23 | self::$menu_data = new Menu($entityManager); // Menu est un modèle mais pas une entité |
23 | $this->page = self::$page_path->getLast(); | 24 | self::$page_path = new Path(); |
24 | $this->root_node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants | 25 | $this->page = self::$page_path->getLast(); |
26 | } | ||
27 | $this->node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants | ||
25 | } | 28 | } |
26 | 29 | ||
30 | public function getNode(): Node | ||
31 | { | ||
32 | return $this->node; | ||
33 | } | ||
34 | public function getArticleNode(): Node | ||
35 | { | ||
36 | return $this->article; | ||
37 | } | ||
38 | |||
27 | public function makeRootNode(string $id = ''): void | 39 | public function makeRootNode(string $id = ''): void |
28 | { | 40 | { |
29 | // on récupère toutes les entrées | 41 | // on récupère toutes les entrées |
@@ -44,25 +56,10 @@ class Director | |||
44 | ->setParameter('id', $id) | 56 | ->setParameter('id', $id) |
45 | ->getResult(); | 57 | ->getResult(); |
46 | } | 58 | } |
47 | $this->feedObjects($bulk_data); | 59 | $this->feedRootNodeObjects($bulk_data); |
48 | } | ||
49 | |||
50 | public function makeArticleNode(string $id = ''): bool | ||
51 | { | ||
52 | $bulk_data = $this->entityManager | ||
53 | ->createQuery('SELECT n FROM App\Entity\Node n WHERE n.article_timestamp = :id') | ||
54 | ->setParameter('id', $id) | ||
55 | ->getResult(); | ||
56 | |||
57 | if(count($bulk_data) === 0){ | ||
58 | return false; | ||
59 | } | ||
60 | |||
61 | $this->root_node = $bulk_data[0]; | ||
62 | return true; | ||
63 | } | 60 | } |
64 | 61 | ||
65 | private function feedObjects(array $bulk_data): void // $bulk_data = tableau de Node | 62 | private function feedRootNodeObjects(array $bulk_data): void // $bulk_data = tableau de Node |
66 | { | 63 | { |
67 | // puis on les range | 64 | // puis on les range |
68 | // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD) | 65 | // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD) |
@@ -71,7 +68,7 @@ class Director | |||
71 | // premier niveau | 68 | // premier niveau |
72 | if($node->getParent() == null) | 69 | if($node->getParent() == null) |
73 | { | 70 | { |
74 | $this->root_node->addChild($node); | 71 | $this->node->addChild($node); |
75 | 72 | ||
76 | // spécifique page article | 73 | // spécifique page article |
77 | if($node->getName() === 'main' && $this->page->getEndOfPath() == 'article'){ | 74 | if($node->getName() === 'main' && $this->page->getEndOfPath() == 'article'){ |
@@ -94,8 +91,50 @@ class Director | |||
94 | } | 91 | } |
95 | } | 92 | } |
96 | 93 | ||
97 | public function getRootNode(): Node | 94 | // récupération d'un article pour modification |
98 | { | 95 | public function makeArticleNode(string $id = '', bool $get_section = false): bool |
99 | return $this->root_node; | 96 | { |
97 | if($get_section){ | ||
98 | $dql = 'SELECT n, p FROM App\Entity\Node n LEFT JOIN n.parent p WHERE n.article_timestamp = :id'; | ||
99 | } | ||
100 | else{ | ||
101 | $dql = 'SELECT n FROM App\Entity\Node n WHERE n.article_timestamp = :id'; | ||
102 | } | ||
103 | // n est l'article et p son $parent | ||
104 | $bulk_data = $this->entityManager | ||
105 | ->createQuery($dql) | ||
106 | ->setParameter('id', $id) | ||
107 | ->getResult(); | ||
108 | |||
109 | if(count($bulk_data) === 0){ | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | if($get_section){ | ||
114 | $this->article = $bulk_data[0]; | ||
115 | $this->makeSectionNode($bulk_data[0]->getParent()->getId()); | ||
116 | } | ||
117 | else{ | ||
118 | $this->article = $bulk_data[0]; | ||
119 | } | ||
120 | |||
121 | return true; | ||
122 | } | ||
123 | |||
124 | // récupération des articles d'un bloc <section> à la création d'un article | ||
125 | public function makeSectionNode(int $section_id): bool | ||
126 | { | ||
127 | $section = $this->entityManager->find('App\Entity\Node', (string)$section_id); | ||
128 | |||
129 | $bulk_data = $this->entityManager | ||
130 | ->createQuery('SELECT n FROM App\Entity\Node n WHERE n.parent = :parent') | ||
131 | ->setParameter('parent', $section) | ||
132 | ->getResult(); | ||
133 | |||
134 | foreach($bulk_data as $article){ | ||
135 | $section->addChild($article); // pas de flush, on ne va pas écrire dans la BDD à chaque nouvelle page | ||
136 | } | ||
137 | $this->node = $section; | ||
138 | return true; | ||
100 | } | 139 | } |
101 | } | 140 | } |
diff --git a/src/controller/Security.php b/src/controller/Security.php index 818a2bd..f9092e2 100644 --- a/src/controller/Security.php +++ b/src/controller/Security.php | |||
@@ -9,7 +9,7 @@ class Security | |||
9 | 'safe'=>1, // protection contre les élements et attributs dangereux | 9 | 'safe'=>1, // protection contre les élements et attributs dangereux |
10 | 10 | ||
11 | // liste blanche d'éléments HTML | 11 | // liste blanche d'éléments HTML |
12 | 'elements'=> 'h1, h2, h3, h4, h5, h6, p, s, em, span, strong, a, ul, ol, li, sup, sub, code, blockquote, div, pre, table, caption, colgroup, col, tbody, tr, th, td, figure, img, figcaption, iframe, small', | 12 | 'elements'=> 'h1, h2, h3, h4, h5, h6, p, br, s, em, span, strong, a, ul, ol, li, sup, sub, code, blockquote, div, pre, table, caption, colgroup, col, tbody, tr, th, td, figure, img, figcaption, iframe, small', |
13 | 13 | ||
14 | // liste noire d'attributs HTML | 14 | // liste noire d'attributs HTML |
15 | 'deny_attribute'=> 'id, class' // on garde 'style' | 15 | 'deny_attribute'=> 'id, class' // on garde 'style' |
diff --git a/src/controller/ajax.php b/src/controller/ajax.php index 86acd39..b5c2e51 100644 --- a/src/controller/ajax.php +++ b/src/controller/ajax.php | |||
@@ -3,6 +3,9 @@ | |||
3 | 3 | ||
4 | declare(strict_types=1); | 4 | declare(strict_types=1); |
5 | 5 | ||
6 | use App\Entity\Article; | ||
7 | use App\Entity\Node; | ||
8 | |||
6 | // détection des requêtes de tinymce | 9 | // détection des requêtes de tinymce |
7 | if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | 10 | if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) |
8 | { | 11 | { |
@@ -15,13 +18,44 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
15 | if(json_last_error() === JSON_ERROR_NONE) | 18 | if(json_last_error() === JSON_ERROR_NONE) |
16 | { | 19 | { |
17 | $id = $json['id']; | 20 | $id = $json['id']; |
18 | $id[0] = 'i'; | ||
19 | $content = Security::secureString($json['content']); | 21 | $content = Security::secureString($json['content']); |
20 | |||
21 | $director = new Director($entityManager); | 22 | $director = new Director($entityManager); |
23 | |||
24 | // nouvel article | ||
25 | if($id[0] === 'n') | ||
26 | { | ||
27 | if($content === ''){ | ||
28 | echo json_encode(['success' => false, 'message' => 'pas de données à sauvegarder']); | ||
29 | die; | ||
30 | } | ||
31 | $section_id = (int)substr($id, 1); // id du bloc <section> | ||
32 | $director->makeSectionNode($section_id); | ||
33 | $node = $director->getNode(); // = <section> | ||
34 | |||
35 | $timestamp = time(); | ||
36 | $date = new \DateTime; | ||
37 | $date->setTimestamp($timestamp); | ||
38 | |||
39 | $article = new Article($content, $date); // le "current" timestamp est obtenu par la BDD | ||
40 | $article_node = new Node('article', 'i' . (string)$timestamp, [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); | ||
41 | |||
42 | $entityManager->persist($article_node); | ||
43 | $entityManager->flush(); | ||
44 | |||
45 | // id_node tout juste généré | ||
46 | //$article_node->getId(); | ||
47 | |||
48 | echo json_encode(['success' => true, 'article_id' => $article_node->getArticleTimestamp()]); | ||
49 | die; | ||
50 | } | ||
51 | // modification article | ||
52 | else{ | ||
53 | $id[0] = 'i'; // id de l'article node | ||
54 | } | ||
55 | |||
22 | if($director->makeArticleNode($id)) // une entrée est trouvée | 56 | if($director->makeArticleNode($id)) // une entrée est trouvée |
23 | { | 57 | { |
24 | $node = $director->getRootNode(); | 58 | $node = $director->getArticleNode(); // article |
25 | switch($json['id'][0]){ | 59 | switch($json['id'][0]){ |
26 | case 'i': | 60 | case 'i': |
27 | $node->getArticle()->setContent($content); | 61 | $node->getArticle()->setContent($content); |
@@ -42,8 +76,9 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
42 | $entityManager->flush(); | 76 | $entityManager->flush(); |
43 | echo json_encode(['success' => true]); | 77 | echo json_encode(['success' => true]); |
44 | } | 78 | } |
45 | else{ | 79 | else |
46 | echo json_encode(['success' => false, 'message' => 'Aucune entrée trouvée en BDD']); | 80 | { |
81 | echo json_encode(['success' => false, 'message' => 'article non identifié']); | ||
47 | } | 82 | } |
48 | } | 83 | } |
49 | else{ | 84 | else{ |
@@ -53,16 +88,18 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
53 | } | 88 | } |
54 | elseif($_GET['action'] === 'delete_article' && isset($json['id'])) | 89 | elseif($_GET['action'] === 'delete_article' && isset($json['id'])) |
55 | { | 90 | { |
56 | $id = $json['id']; | ||
57 | |||
58 | $director = new Director($entityManager); | 91 | $director = new Director($entityManager); |
59 | $director->makeArticleNode($id); | 92 | $director->makeArticleNode($json['id'], true); |
60 | $node = $director->getRootNode(); | 93 | $article = $director->getArticleNode(); |
61 | $entityManager->remove($node); | 94 | $section = $director->getNode(); |
95 | |||
96 | $entityManager->remove($article); | ||
97 | $section->removeChild($article); | ||
98 | $section->sortChildren(true); // régénère les positions | ||
62 | $entityManager->flush(); | 99 | $entityManager->flush(); |
63 | 100 | ||
64 | // test avec une nouvelle requête qui ne devrait rien trouver | 101 | // test avec une nouvelle requête qui ne devrait rien trouver |
65 | if(!$director->makeArticleNode($id)) | 102 | if(!$director->makeArticleNode($json['id'])) |
66 | { | 103 | { |
67 | echo json_encode(['success' => true]); | 104 | echo json_encode(['success' => true]); |
68 | 105 | ||
@@ -78,14 +115,25 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
78 | elseif($_GET['action'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) | 115 | elseif($_GET['action'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) |
79 | { | 116 | { |
80 | $director = new Director($entityManager); | 117 | $director = new Director($entityManager); |
81 | $director->makeArticleNode($json['id1']); | 118 | $director->makeArticleNode($json['id1'], true); |
82 | $node1 = $director->getRootNode(); | 119 | $article1 = $director->getArticleNode(); |
83 | $director->makeArticleNode($json['id2']); | 120 | $section = $director->getNode(); |
84 | $node2 = $director->getRootNode(); | 121 | |
85 | 122 | $section->sortChildren(true); // régénère les positions avant inversion | |
86 | $tmp = $node1->getPosition(); | 123 | |
87 | $node1->setPosition($node2->getPosition()); | 124 | $article2; |
88 | $node2->setPosition($tmp); | 125 | foreach($section->getChildren() as $child){ |
126 | if($child->getArticleTimestamp() === $json['id2']) // type string | ||
127 | { | ||
128 | $article2 = $child; | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | // inversion | ||
134 | $tmp = $article1->getPosition(); | ||
135 | $article1->setPosition($article2->getPosition()); | ||
136 | $article2->setPosition($tmp); | ||
89 | $entityManager->flush(); | 137 | $entityManager->flush(); |
90 | 138 | ||
91 | echo json_encode(['success' => true]); | 139 | echo json_encode(['success' => true]); |
@@ -99,7 +147,7 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
99 | 147 | ||
100 | $director = new Director($entityManager); | 148 | $director = new Director($entityManager); |
101 | $director->makeArticleNode($id); | 149 | $director->makeArticleNode($id); |
102 | $node = $director->getRootNode(); | 150 | $node = $director->getArticleNode(); |
103 | $node->getArticle()->setDateTime($date); | 151 | $node->getArticle()->setDateTime($date); |
104 | $entityManager->flush(); | 152 | $entityManager->flush(); |
105 | 153 | ||
diff --git a/src/model/entities/Article.php b/src/model/entities/Article.php index 601e573..dc2d78b 100644 --- a/src/model/entities/Article.php +++ b/src/model/entities/Article.php | |||
@@ -20,7 +20,7 @@ class Article | |||
20 | 20 | ||
21 | // datetime_immutable permet à la base de toujours gérer cette clé primaire correctement | 21 | // datetime_immutable permet à la base de toujours gérer cette clé primaire correctement |
22 | #[ORM\Column(type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'], unique: true)] | 22 | #[ORM\Column(type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'], unique: true)] |
23 | private \DateTime $date_time; // le type datetime de doctrine convertit en type \DateTime de PHP | 23 | private ?\DateTime $date_time; // le type datetime de doctrine convertit en type \DateTime de PHP |
24 | 24 | ||
25 | #[ORM\Column(type: "string")] | 25 | #[ORM\Column(type: "string")] |
26 | private string $title; | 26 | private string $title; |
@@ -40,8 +40,12 @@ class Article | |||
40 | )] | 40 | )] |
41 | private Collection $images; | 41 | private Collection $images; |
42 | 42 | ||
43 | public function __construct() | 43 | public function __construct(string $content, \DateTime $date_time = null, string $title = '', string $preview = '') |
44 | { | 44 | { |
45 | $this->date_time = $date_time; | ||
46 | $this->title = $title; | ||
47 | $this->preview = $preview; | ||
48 | $this->content = $content; | ||
45 | $this->images = new ArrayCollection(); // initialisation nécessaire | 49 | $this->images = new ArrayCollection(); // initialisation nécessaire |
46 | } | 50 | } |
47 | 51 | ||
diff --git a/src/model/entities/Node.php b/src/model/entities/Node.php index 9240413..c9b310a 100644 --- a/src/model/entities/Node.php +++ b/src/model/entities/Node.php | |||
@@ -65,32 +65,6 @@ class Node | |||
65 | $this->article = $article; | 65 | $this->article = $article; |
66 | } | 66 | } |
67 | 67 | ||
68 | public function addChild(self $child): void | ||
69 | { | ||
70 | $this->children[] = $child; | ||
71 | $this->sortChildren(); | ||
72 | } | ||
73 | |||
74 | // utiliser $position pour afficher les éléments dans l'ordre | ||
75 | private function sortChildren(): void | ||
76 | { | ||
77 | $iteration = count($this->children); | ||
78 | while($iteration > 1) | ||
79 | { | ||
80 | for($i = 0; $i < $iteration - 1; $i++) | ||
81 | { | ||
82 | //echo '<br>' . $this->children[$i]->getPosition() . ' - ' . $this->children[$i + 1]->getPosition(); | ||
83 | if($this->children[$i]->getPosition() > $this->children[$i + 1]->getPosition()) | ||
84 | { | ||
85 | $tmp = $this->children[$i]; | ||
86 | $this->children[$i] = $this->children[$i + 1]; | ||
87 | $this->children[$i + 1] = $tmp; | ||
88 | } | ||
89 | } | ||
90 | $iteration--; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | // pfff... | 68 | // pfff... |
95 | public function getId(): int | 69 | public function getId(): int |
96 | { | 70 | { |
@@ -156,6 +130,51 @@ class Node | |||
156 | { | 130 | { |
157 | return $this->children; | 131 | return $this->children; |
158 | } | 132 | } |
133 | public function addChild(self $child): void | ||
134 | { | ||
135 | $this->children[] = $child; | ||
136 | $this->sortChildren(false); | ||
137 | } | ||
138 | // utiliser $position pour afficher les éléments dans l'ordre | ||
139 | public function sortChildren(bool $reposition = false): void | ||
140 | { | ||
141 | // ordre du tableau des enfants | ||
142 | // inefficace quand des noeuds ont la même position | ||
143 | |||
144 | // tri par insertion | ||
145 | for($i = 1; $i < count($this->children); $i++) | ||
146 | { | ||
147 | $tmp = $this->children[$i]; | ||
148 | $j = $i - 1; | ||
149 | |||
150 | // Déplacez les éléments du tableau qui sont plus grands que la clé | ||
151 | // à une position devant leur position actuelle | ||
152 | while ($j >= 0 && $this->children[$j]->getPosition() > $tmp->getPosition()) { | ||
153 | $this->children[$j + 1] = $this->children[$j]; | ||
154 | $j = $j - 1; | ||
155 | } | ||
156 | $this->children[$j + 1] = $tmp; | ||
157 | } | ||
158 | |||
159 | // nouvelles positions | ||
160 | if($reposition){ | ||
161 | $i = 1; | ||
162 | foreach($this->children as $child){ | ||
163 | $child->setPosition($i); | ||
164 | $i++; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | public function removeChild(self $child): void | ||
169 | { | ||
170 | foreach($this->children as $key => $object){ | ||
171 | if($object->getId() === $child->getId()){ | ||
172 | unset($this->children[$key]); | ||
173 | } | ||
174 | break; | ||
175 | } | ||
176 | $this->children = array_values($this->children); // réindexer pour supprimer la case vide | ||
177 | } | ||
159 | 178 | ||
160 | public function getTempChild(): ?self // peut renvoyer null | 179 | public function getTempChild(): ?self // peut renvoyer null |
161 | { | 180 | { |
diff --git a/src/view/AbstractBuilder.php b/src/view/AbstractBuilder.php index cd2b361..285ebc3 100644 --- a/src/view/AbstractBuilder.php +++ b/src/view/AbstractBuilder.php | |||
@@ -7,6 +7,12 @@ abstract class AbstractBuilder | |||
7 | { | 7 | { |
8 | protected const VIEWS_PATH = '../src/view/templates/'; | 8 | protected const VIEWS_PATH = '../src/view/templates/'; |
9 | protected string $html = ''; | 9 | protected string $html = ''; |
10 | protected int $id_node; | ||
11 | |||
12 | protected function __construct(Node $node) | ||
13 | { | ||
14 | $this->id_node = $node->getId(); | ||
15 | } | ||
10 | 16 | ||
11 | protected function useChildrenBuilder(Node $node): void | 17 | protected function useChildrenBuilder(Node $node): void |
12 | { | 18 | { |
diff --git a/src/view/ArticleBuilder.php b/src/view/ArticleBuilder.php index f86f9bd..1f5dbb8 100644 --- a/src/view/ArticleBuilder.php +++ b/src/view/ArticleBuilder.php | |||
@@ -25,29 +25,29 @@ class ArticleBuilder extends AbstractBuilder | |||
25 | // partage | 25 | // partage |
26 | $share_link = new URL(['page' => CURRENT_PAGE], $id); | 26 | $share_link = new URL(['page' => CURRENT_PAGE], $id); |
27 | $share_js = 'onclick="copyInClipBoard(\'' . $share_link . '\')"'; | 27 | $share_js = 'onclick="copyInClipBoard(\'' . $share_link . '\')"'; |
28 | $share_button = '<a class="share" href="' . $share_link . '" ' . $share_js . '><img class="action_icon" src="assets/share.svg"></a>' . "\n"; | 28 | $share_button = '<p class="share" ' . $share_js . '><img class="action_icon" src="assets/share.svg"></p>' . "\n"; |
29 | 29 | ||
30 | // modifier un article | 30 | // modifier un article |
31 | $admin_buttons = ''; | 31 | $admin_buttons = ''; |
32 | if($_SESSION['admin']) | 32 | if($_SESSION['admin']) |
33 | { | 33 | { |
34 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; | 34 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; |
35 | $modify_article = '<p id="edit-' . $id . '"><a href="#"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></a></p>' . "\n"; | 35 | $modify_article = '<p id="edit-' . $id . '"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; |
36 | 36 | ||
37 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | 37 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; |
38 | $up_button = '<p id="position_up-' . $id . '"><a href="#"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></a></p>' . "\n"; | 38 | $up_button = '<p id="position_up-' . $id . '"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; |
39 | 39 | ||
40 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | 40 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; |
41 | $down_button = '<p id="position_down-' . $id . '"><a href="#"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></a></p>' . "\n"; | 41 | $down_button = '<p id="position_down-' . $id . '"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; |
42 | 42 | ||
43 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | 43 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; |
44 | $delete_article = '<p id="delete-' . $id . '"><a href="#"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></a></p>' . "\n"; | 44 | $delete_article = '<p id="delete-' . $id . '"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; |
45 | 45 | ||
46 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; | 46 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; |
47 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"><a href="#"><button ' . $close_js . '>Annuler</button></a></p>'; | 47 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"><button ' . $close_js . '>Annuler</button></p>'; |
48 | 48 | ||
49 | $submit_js = 'onclick="submitArticle(\'' . $id . '\')"'; | 49 | $submit_js = 'onclick="submitArticle(\'' . $id . '\')"'; |
50 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><a href="#"><button ' . $submit_js . '>Valider</button></a></p>'; | 50 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; |
51 | 51 | ||
52 | $admin_buttons = $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; | 52 | $admin_buttons = $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; |
53 | } | 53 | } |
diff --git a/src/view/BlogBuilder.php b/src/view/BlogBuilder.php index 8c2125f..ca020b2 100644 --- a/src/view/BlogBuilder.php +++ b/src/view/BlogBuilder.php | |||
@@ -7,6 +7,7 @@ class BlogBuilder extends AbstractBuilder | |||
7 | { | 7 | { |
8 | public function __construct(Node $node) | 8 | public function __construct(Node $node) |
9 | { | 9 | { |
10 | parent::__construct($node); | ||
10 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; | 11 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; |
11 | 12 | ||
12 | if(file_exists($viewFile)) | 13 | if(file_exists($viewFile)) |
@@ -18,26 +19,44 @@ class BlogBuilder extends AbstractBuilder | |||
18 | 19 | ||
19 | // ajouter un article | 20 | // ajouter un article |
20 | $new_article = ''; | 21 | $new_article = ''; |
21 | $new_article_admin_buttons = ''; | ||
22 | if($_SESSION['admin']) | 22 | if($_SESSION['admin']) |
23 | { | 23 | { |
24 | $id = 'new'; | 24 | $id = 'n' . $this->id_node; |
25 | |||
26 | //$link = new URL(['page' => CURRENT_PAGE, 'action' => 'open_editor']); | ||
27 | $js = 'onclick="openEditor(\'' . $id . '\')"'; | 25 | $js = 'onclick="openEditor(\'' . $id . '\')"'; |
28 | //$new_article = '<article><a href="' . $link . '"><button>Nouvel article</button></a></article>'; | 26 | |
29 | $new_article = '<article><p id="new"></p>' . "\n" . | 27 | $share_button = '<p class="share hidden"><img class="action_icon" src="assets/share.svg"></p>'; |
30 | '<p id="new-' . $id . '"><a href="#"><button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></a></p>'; | 28 | $html = ''; |
29 | |||
30 | $new_button = '<p id="new-' . $id . '">' . "\n" . | ||
31 | '<button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></p>'; | ||
32 | |||
33 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; | ||
34 | $modify_article = '<p id="edit-' . $id . '" class="hidden"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; | ||
35 | |||
36 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | ||
37 | $up_button = '<p id="position_up-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; | ||
38 | |||
39 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | ||
40 | $down_button = '<p id="position_down-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; | ||
41 | |||
42 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | ||
43 | $delete_article = '<p id="delete-' . $id . '" class="hidden"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; | ||
31 | 44 | ||
32 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; | 45 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; |
33 | $close_editor = '<div class="article_admin_zone"><p id="cancel-' . $id . '" class="hidden"><a href="#"><button ' . $close_js . '>Annuler</button></a></p>'; | 46 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"><button ' . $close_js . '>Annuler</button></p>'; |
34 | 47 | ||
35 | $submit_js = 'onclick="submitArticle(\'' . $id . '\')"'; | 48 | $submit_js = 'onclick="submitArticle(\'' . $id . '\', \'\', clone' . $this->id_node . ')"'; |
36 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><a href="#"><button ' . $submit_js . '>Valider</button></a></p></div></article>'; | 49 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; |
37 | 50 | ||
38 | $new_article_admin_buttons = $close_editor . $submit_article; | 51 | $admin_buttons = $new_button . $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; |
52 | |||
53 | // squelette d'un nouvel article | ||
54 | ob_start(); | ||
55 | require self::VIEWS_PATH . 'article.php'; | ||
56 | $new_article = ob_get_clean(); | ||
39 | } | 57 | } |
40 | 58 | ||
59 | // articles existants | ||
41 | $this->useChildrenBuilder($node); | 60 | $this->useChildrenBuilder($node); |
42 | $content = $this->html; | 61 | $content = $this->html; |
43 | 62 | ||
diff --git a/src/view/GaleryBuilder.php b/src/view/GaleryBuilder.php index 89be2b1..a895d70 100644 --- a/src/view/GaleryBuilder.php +++ b/src/view/GaleryBuilder.php | |||
@@ -7,6 +7,7 @@ class GaleryBuilder extends AbstractBuilder | |||
7 | { | 7 | { |
8 | public function __construct(Node $node) | 8 | public function __construct(Node $node) |
9 | { | 9 | { |
10 | parent::__construct($node); | ||
10 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; | 11 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; |
11 | 12 | ||
12 | if(file_exists($viewFile)) | 13 | if(file_exists($viewFile)) |
@@ -18,26 +19,44 @@ class GaleryBuilder extends AbstractBuilder | |||
18 | 19 | ||
19 | // ajouter un article | 20 | // ajouter un article |
20 | $new_article = ''; | 21 | $new_article = ''; |
21 | $new_article_admin_buttons = ''; | ||
22 | if($_SESSION['admin']) | 22 | if($_SESSION['admin']) |
23 | { | 23 | { |
24 | $id = 'new'; | 24 | $id = 'n' . $this->id_node; |
25 | |||
26 | //$link = new URL(['page' => CURRENT_PAGE, 'action' => 'open_editor']); | ||
27 | $js = 'onclick="openEditor(\'' . $id . '\')"'; | 25 | $js = 'onclick="openEditor(\'' . $id . '\')"'; |
28 | //$new_article = '<article><a href="' . $link . '"><button>Nouvel article</button></a></article>'; | 26 | |
29 | $new_article = '<article><p id="new"></p>' . "\n" . | 27 | $share_button = '<p class="share hidden"><img class="action_icon" src="assets/share.svg"></p>'; |
30 | '<p id="new-' . $id . '"><a href="#"><button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></a></p>'; | 28 | $html = ''; |
29 | |||
30 | $new_button = '<p id="new-' . $id . '">' . "\n" . | ||
31 | '<button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></p>'; | ||
32 | |||
33 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; | ||
34 | $modify_article = '<p id="edit-' . $id . '" class="hidden"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; | ||
35 | |||
36 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | ||
37 | $up_button = '<p id="position_up-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; | ||
38 | |||
39 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | ||
40 | $down_button = '<p id="position_down-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; | ||
41 | |||
42 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | ||
43 | $delete_article = '<p id="delete-' . $id . '" class="hidden"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; | ||
31 | 44 | ||
32 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; | 45 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; |
33 | $close_editor = '<div class="article_admin_zone"><p id="cancel-' . $id . '" class="hidden"><a href="#"><button ' . $close_js . '>Annuler</button></a></p>'; | 46 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"><button ' . $close_js . '>Annuler</button></p>'; |
34 | 47 | ||
35 | $submit_js = 'onclick="submitArticle(\'' . $id . '\')"'; | 48 | $submit_js = 'onclick="submitArticle(\'' . $id . '\', \'\', clone' . $this->id_node . ')"'; |
36 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><a href="#"><button ' . $submit_js . '>Valider</button></a></p></div></article>'; | 49 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; |
37 | 50 | ||
38 | $new_article_admin_buttons = $close_editor . $submit_article; | 51 | $admin_buttons = $new_button . $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; |
52 | |||
53 | // squelette d'un nouvel article | ||
54 | ob_start(); | ||
55 | require self::VIEWS_PATH . 'article.php'; | ||
56 | $new_article = ob_get_clean(); | ||
39 | } | 57 | } |
40 | 58 | ||
59 | // articles existants | ||
41 | $this->useChildrenBuilder($node); | 60 | $this->useChildrenBuilder($node); |
42 | $content = $this->html; | 61 | $content = $this->html; |
43 | 62 | ||
diff --git a/src/view/GridBuilder.php b/src/view/GridBuilder.php index 6e16d46..e183e6f 100644 --- a/src/view/GridBuilder.php +++ b/src/view/GridBuilder.php | |||
@@ -7,6 +7,7 @@ class GridBuilder extends AbstractBuilder | |||
7 | { | 7 | { |
8 | public function __construct(Node $node) | 8 | public function __construct(Node $node) |
9 | { | 9 | { |
10 | parent::__construct($node); | ||
10 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; | 11 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; |
11 | 12 | ||
12 | if(file_exists($viewFile)) | 13 | if(file_exists($viewFile)) |
@@ -18,32 +19,50 @@ class GridBuilder extends AbstractBuilder | |||
18 | 19 | ||
19 | // ajouter un article | 20 | // ajouter un article |
20 | $new_article = ''; | 21 | $new_article = ''; |
21 | $new_article_admin_buttons = ''; | ||
22 | if($_SESSION['admin']) | 22 | if($_SESSION['admin']) |
23 | { | 23 | { |
24 | $id = 'new'; | 24 | $id = 'n' . $this->id_node; |
25 | $js = 'onclick="openEditor(\'' . $id . '\')"'; | 25 | $js = 'onclick="openEditor(\'' . $id . '\')"'; |
26 | 26 | ||
27 | if(Director::$page_path->getLast()->getEndOfPath() === 'accueil') | 27 | $share_button = '<p class="share hidden"><img class="action_icon" src="assets/share.svg"></p>'; |
28 | { | 28 | $html = ''; |
29 | $new_article = '<article><p id="new"></p>' . "\n" . | 29 | |
30 | '<p><a href="' . new URL(['page' => 'article']) . '"><button><img class="action_icon" src="assets/edit.svg">Nouvel article</button></a></p>'; | 30 | if(CURRENT_PAGE === 'accueil'){ |
31 | $new_button = '<p><a class="link_to_article" href="' . new URL(['page' => 'article', 'id' => $id]) . '"> | ||
32 | <button><img class="action_icon" src="assets/book-open.svg">Nouvel article</button></a></p>'; | ||
31 | } | 33 | } |
32 | else | 34 | else{ |
33 | { | 35 | $new_button = '<p id="new-' . $id . '">' . "\n" . |
34 | $new_article = '<article><p id="new"></p>' . "\n" . | 36 | '<button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></p>'; |
35 | '<p id="new-' . $id . '"><a href="#"><button ' . $js . '><img class="action_icon" src="assets/edit.svg">Nouvel article</button></a></p>'; | ||
36 | } | 37 | } |
38 | |||
39 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; | ||
40 | $modify_article = '<p id="edit-' . $id . '" class="hidden"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; | ||
41 | |||
42 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | ||
43 | $up_button = '<p id="position_up-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; | ||
37 | 44 | ||
45 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | ||
46 | $down_button = '<p id="position_down-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; | ||
47 | |||
48 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | ||
49 | $delete_article = '<p id="delete-' . $id . '" class="hidden"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; | ||
50 | |||
38 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; | 51 | $close_js = 'onclick="closeEditor(\'' . $id . '\')"'; |
39 | $close_editor = '<div class="article_admin_zone"><p id="cancel-' . $id . '" class="hidden"><a href="#"><button ' . $close_js . '>Annuler</button></a></p>'; | 52 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"><button ' . $close_js . '>Annuler</button></p>'; |
40 | 53 | ||
41 | $submit_js = 'onclick="submitArticle(\'' . $id . '\')"'; | 54 | $submit_js = 'onclick="submitArticle(\'' . $id . '\', \'\', clone' . $this->id_node . ')"'; |
42 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><a href="#"><button ' . $submit_js . '>Valider</button></a></p></div></article>'; | 55 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; |
43 | 56 | ||
44 | $new_article_admin_buttons = $close_editor . $submit_article; | 57 | $admin_buttons = $new_button . $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; |
58 | |||
59 | // squelette d'un nouvel article | ||
60 | ob_start(); | ||
61 | require self::VIEWS_PATH . 'article.php'; | ||
62 | $new_article = ob_get_clean(); | ||
45 | } | 63 | } |
46 | 64 | ||
65 | // articles existants | ||
47 | $this->useChildrenBuilder($node); | 66 | $this->useChildrenBuilder($node); |
48 | $content = $this->html; | 67 | $content = $this->html; |
49 | 68 | ||
diff --git a/src/view/templates/article.php b/src/view/templates/article.php index f3ab32f..c57c1cb 100644 --- a/src/view/templates/article.php +++ b/src/view/templates/article.php | |||
@@ -10,5 +10,4 @@ | |||
10 | <?= $admin_buttons ?> | 10 | <?= $admin_buttons ?> |
11 | </div> | 11 | </div> |
12 | </div> | 12 | </div> |
13 | |||
14 | </article> \ No newline at end of file | 13 | </article> \ No newline at end of file |
diff --git a/src/view/templates/blog.php b/src/view/templates/blog.php index 35cac8b..e2066c8 100644 --- a/src/view/templates/blog.php +++ b/src/view/templates/blog.php | |||
@@ -1,6 +1,10 @@ | |||
1 | <section class="blog"> | 1 | <section class="blog" id="<?= $this->id_node ?>"> |
2 | <h3><?= $title ?></h3> | 2 | <h3><?= $title ?></h3> |
3 | <?= $new_article ?> | 3 | <?= $new_article ?> |
4 | <?= $new_article_admin_buttons ?> | 4 | <script> |
5 | var clone<?= $this->id_node ?> = document.currentScript.previousElementSibling.cloneNode(true); | ||
6 | </script> | ||
7 | <div> | ||
5 | <?= $content ?> | 8 | <?= $content ?> |
9 | </div> | ||
6 | </section> \ No newline at end of file | 10 | </section> \ No newline at end of file |
diff --git a/src/view/templates/galery.php b/src/view/templates/galery.php index 306526f..246c4dd 100644 --- a/src/view/templates/galery.php +++ b/src/view/templates/galery.php | |||
@@ -1,9 +1,10 @@ | |||
1 | <section class="galery"> | 1 | <section class="galery" id="<?= $this->id_node ?>"> |
2 | <h3><?= $title ?></h3> | 2 | <h3><?= $title ?></h3> |
3 | <?= $new_article ?> | 3 | <?= $new_article ?> |
4 | <?= $new_article_admin_buttons ?> | 4 | <script> |
5 | var clone<?= $this->id_node ?> = document.currentScript.previousElementSibling.cloneNode(true); | ||
6 | </script> | ||
5 | <div class="galery_photos"> | 7 | <div class="galery_photos"> |
6 | <a><p></p></a> | ||
7 | <?= $content ?> | 8 | <?= $content ?> |
8 | </div> | 9 | </div> |
9 | <script>enableGaleryScroller();</script> | 10 | <script>enableGaleryScroller();</script> |
diff --git a/src/view/templates/grid.php b/src/view/templates/grid.php index a09ed40..f9e441d 100644 --- a/src/view/templates/grid.php +++ b/src/view/templates/grid.php | |||
@@ -1,7 +1,9 @@ | |||
1 | <section class="grid"> | 1 | <section class="grid" id="<?= $this->id_node ?>"> |
2 | <h3><?= $title ?></h3> | 2 | <h3><?= $title ?></h3> |
3 | <?= $new_article ?> | 3 | <?= $new_article ?> |
4 | <?= $new_article_admin_buttons ?> | 4 | <script> |
5 | var clone<?= $this->id_node ?> = document.currentScript.previousElementSibling.cloneNode(true); | ||
6 | </script> | ||
5 | <div class="grid_columns"> | 7 | <div class="grid_columns"> |
6 | <?= $content ?> | 8 | <?= $content ?> |
7 | </div> | 9 | </div> |