diff options
author | polo <ordipolo@gmx.fr> | 2025-04-27 23:58:46 +0200 |
---|---|---|
committer | polo <ordipolo@gmx.fr> | 2025-04-27 23:58:46 +0200 |
commit | 962d315ec0c99974df3dc2261bf94c54ca8cdbdd (patch) | |
tree | 7463f74a722e759067daf8c3ef43202a60352759 | |
parent | a3ba7dde60dc1c94b7170ec28266a966e5004d33 (diff) | |
download | cms-962d315ec0c99974df3dc2261bf94c54ca8cdbdd.zip |
page menu et chemins, partie3
-rw-r--r-- | public/css/menu.css | 14 | ||||
-rw-r--r-- | public/js/main.js | 93 | ||||
-rw-r--r-- | public/js/menu.js | 240 | ||||
-rw-r--r-- | src/controller/ajax.php | 87 | ||||
-rw-r--r-- | src/controller/installation.php | 14 | ||||
-rw-r--r-- | src/controller/post.php | 82 | ||||
-rw-r--r-- | src/model/Position.php | 22 | ||||
-rw-r--r-- | src/model/entities/Page.php | 16 | ||||
-rw-r--r-- | src/view/MenuBuilder.php | 46 | ||||
-rw-r--r-- | src/view/templates/menu.php | 9 |
10 files changed, 473 insertions, 150 deletions
diff --git a/public/css/menu.css b/public/css/menu.css index cce1d43..5016610 100644 --- a/public/css/menu.css +++ b/public/css/menu.css | |||
@@ -4,11 +4,19 @@ | |||
4 | { | 4 | { |
5 | padding: 0 20px; | 5 | padding: 0 20px; |
6 | } | 6 | } |
7 | .menu_edit_entry | ||
8 | { | ||
9 | margin-left: 29px; | ||
10 | } | ||
7 | .menu img | 11 | .menu img |
8 | { | 12 | { |
9 | width: 20px; | 13 | width: 20px; |
10 | vertical-align: middle; | 14 | vertical-align: middle; |
11 | } | 15 | } |
16 | .menu form | ||
17 | { | ||
18 | display: inline; | ||
19 | } | ||
12 | 20 | ||
13 | /* explications pour l'utiisateur */ | 21 | /* explications pour l'utiisateur */ |
14 | .menu aside | 22 | .menu aside |
@@ -58,6 +66,7 @@ input | |||
58 | { | 66 | { |
59 | background-color: white; | 67 | background-color: white; |
60 | padding: 10px; | 68 | padding: 10px; |
69 | margin-top: 10px; | ||
61 | } | 70 | } |
62 | .menu .new_entry_buttons p | 71 | .menu .new_entry_buttons p |
63 | { | 72 | { |
@@ -65,8 +74,5 @@ input | |||
65 | } | 74 | } |
66 | 75 | ||
67 | @media screen and (min-width: 80rem) { | 76 | @media screen and (min-width: 80rem) { |
68 | i | 77 | i{} |
69 | { | ||
70 | /*display: none;*/ | ||
71 | } | ||
72 | } \ No newline at end of file | 78 | } \ No newline at end of file |
diff --git a/public/js/main.js b/public/js/main.js index f74c670..e278325 100644 --- a/public/js/main.js +++ b/public/js/main.js | |||
@@ -202,97 +202,4 @@ function findParent(element, tag_name){ | |||
202 | element = element.parentElement; | 202 | element = element.parentElement; |
203 | } | 203 | } |
204 | return null; | 204 | return null; |
205 | } | ||
206 | |||
207 | |||
208 | /* page Menu et chemins */ | ||
209 | function moveOneLevelUp(){} | ||
210 | function moveOneLevelDown(){} | ||
211 | |||
212 | function switchMenuPositions(page_id, direction) | ||
213 | { | ||
214 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
215 | const clicked_menu_entry = document.getElementById(page_id); // div parente du bouton | ||
216 | var other_entry = null; | ||
217 | |||
218 | // pas bon | ||
219 | if(direction == 'down'){ | ||
220 | other_entry = clicked_menu_entry.nextElementSibling; | ||
221 | } | ||
222 | else if(direction == 'up'){ | ||
223 | other_entry = clicked_menu_entry.previousElementSibling; | ||
224 | } | ||
225 | |||
226 | if(other_entry == null){ | ||
227 | console.log('Inversion impossible'); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | fetch('index.php?menu_edit=switch_positions', { | ||
232 | method: 'POST', | ||
233 | headers: { | ||
234 | 'Content-Type': 'application/json' | ||
235 | }, | ||
236 | body: JSON.stringify({ id1: clicked_menu_entry.id, id2: other_entry.id }) | ||
237 | }) | ||
238 | .then(response => response.json()) | ||
239 | .then(data => { | ||
240 | if(data.success) | ||
241 | { | ||
242 | if(direction == 'down'){ | ||
243 | clicked_menu_entry.parentElement.insertBefore(other_entry, clicked_menu_entry); | ||
244 | console.log('Inversion réussie'); | ||
245 | } | ||
246 | else if(direction == 'up'){ | ||
247 | other_entry.parentElement.insertBefore(clicked_menu_entry, other_entry); | ||
248 | console.log('Inversion réussie'); | ||
249 | } | ||
250 | else{ | ||
251 | console.error('Échec de l\'inversion'); | ||
252 | } | ||
253 | |||
254 | nav_zone.innerHTML = ''; | ||
255 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
256 | } | ||
257 | else { | ||
258 | |||
259 | console.error('Échec de l\'inversion'); | ||
260 | } | ||
261 | }) | ||
262 | .catch(error => { | ||
263 | console.error('Erreur:', error); | ||
264 | }); | ||
265 | } | ||
266 | |||
267 | function checkMenuEntry(page_id){ | ||
268 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
269 | const clicked_menu_entry = document.getElementById(page_id); // div parente du bouton | ||
270 | const checkbox = clicked_menu_entry.querySelector("input"); | ||
271 | let color; | ||
272 | |||
273 | fetch('index.php?menu_edit=displayInMenu', { | ||
274 | method: 'POST', | ||
275 | headers: { | ||
276 | 'Content-Type': 'application/json' | ||
277 | }, | ||
278 | body: JSON.stringify({ id: clicked_menu_entry.id, checked: checkbox.checked }) | ||
279 | }) | ||
280 | .then(response => response.json()) | ||
281 | .then(data => { | ||
282 | if(data.success) | ||
283 | { | ||
284 | color = checkbox.checked ? "#ff1d04" : "grey"; | ||
285 | clicked_menu_entry.querySelector("button").style.color = color; | ||
286 | |||
287 | nav_zone.innerHTML = ''; | ||
288 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
289 | } | ||
290 | else { | ||
291 | |||
292 | console.error('Échec de l\'inversion'); | ||
293 | } | ||
294 | }) | ||
295 | .catch(error => { | ||
296 | console.error('Erreur:', error); | ||
297 | }); | ||
298 | } \ No newline at end of file | 205 | } \ No newline at end of file |
diff --git a/public/js/menu.js b/public/js/menu.js new file mode 100644 index 0000000..a864597 --- /dev/null +++ b/public/js/menu.js | |||
@@ -0,0 +1,240 @@ | |||
1 | // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions | ||
2 | function moveOneLevelUp(page_id) | ||
3 | { | ||
4 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
5 | const menu_edit_buttons = document.getElementById("menu_edit_buttons"); // div englobant le html généré par MenuBuilder | ||
6 | |||
7 | fetch('index.php?menu_edit=move_one_level_up', { | ||
8 | method: 'POST', | ||
9 | headers: { | ||
10 | 'Content-Type': 'application/json' | ||
11 | }, | ||
12 | body: JSON.stringify({ id: page_id }) | ||
13 | }) | ||
14 | .then(response => response.json()) | ||
15 | .then(data => { | ||
16 | if(data.success) | ||
17 | { | ||
18 | console.log(data); | ||
19 | // affichage | ||
20 | nav_zone.innerHTML = ''; | ||
21 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
22 | menu_edit_buttons.innerHTML = ''; | ||
23 | menu_edit_buttons.insertAdjacentHTML('afterbegin', data.menu_buttons); | ||
24 | } | ||
25 | else { | ||
26 | |||
27 | console.error('Échec du déplacement'); | ||
28 | } | ||
29 | }) | ||
30 | .catch(error => { | ||
31 | console.error('Erreur:', error); | ||
32 | }); | ||
33 | } | ||
34 | |||
35 | // flèche droite =>: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent | ||
36 | function moveOneLevelDown(page_id) | ||
37 | { | ||
38 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
39 | const menu_edit_buttons = document.getElementById("menu_edit_buttons"); // div englobant le html généré par MenuBuilder | ||
40 | |||
41 | fetch('index.php?menu_edit=move_one_level_down', { | ||
42 | method: 'POST', | ||
43 | headers: { | ||
44 | 'Content-Type': 'application/json' | ||
45 | }, | ||
46 | body: JSON.stringify({ id: page_id }) | ||
47 | }) | ||
48 | .then(response => response.json()) | ||
49 | .then(data => { | ||
50 | if(data.success) | ||
51 | { | ||
52 | console.log(data); | ||
53 | // affichage | ||
54 | nav_zone.innerHTML = ''; | ||
55 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
56 | menu_edit_buttons.innerHTML = ''; | ||
57 | menu_edit_buttons.insertAdjacentHTML('afterbegin', data.menu_buttons); | ||
58 | } | ||
59 | else { | ||
60 | console.error('Échec du déplacement'); | ||
61 | } | ||
62 | }) | ||
63 | .catch(error => { | ||
64 | console.error('Erreur:', error); | ||
65 | }); | ||
66 | |||
67 | /*const element = document.getElementById(page_id); // div parente du bouton cliqué | ||
68 | let previous_element = element.previousElementSibling; | ||
69 | |||
70 | if(previous_element != null) | ||
71 | { | ||
72 | // si l'element précédent n'a pas de chemin relatif, donc est une URL, on vérifie le précédent également | ||
73 | if(previous_element.querySelector(".path") == null){ | ||
74 | let test_previous = previous_element; | ||
75 | while(test_previous.querySelector(".url") != null){ | ||
76 | console.log(test_previous); | ||
77 | //if() | ||
78 | test_previous = test_previous.previousElementSibling; | ||
79 | if(test_previous == null){ | ||
80 | console.log("pas d'élément précédent"); | ||
81 | return; | ||
82 | } | ||
83 | console.log(test_previous); | ||
84 | } | ||
85 | previous_element = test_previous; | ||
86 | } | ||
87 | |||
88 | fetch('index.php?menu_edit=move_one_level_down', { | ||
89 | method: 'POST', | ||
90 | headers: { | ||
91 | 'Content-Type': 'application/json' | ||
92 | }, | ||
93 | body: JSON.stringify({ id: element.id }) | ||
94 | }) | ||
95 | .then(response => response.json()) | ||
96 | .then(data => { | ||
97 | if(data.success) | ||
98 | { | ||
99 | // | ||
100 | |||
101 | // menu régénéré | ||
102 | nav_zone.innerHTML = ''; | ||
103 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
104 | } | ||
105 | else { | ||
106 | |||
107 | console.error('Échec de l\'inversion'); | ||
108 | } | ||
109 | }) | ||
110 | .catch(error => { | ||
111 | console.error('Erreur:', error); | ||
112 | }); | ||
113 | |||
114 | // nouveau parent | ||
115 | let level_div = previous_element.querySelector(".level"); | ||
116 | if(level_div == null){ | ||
117 | // créer une <div class="level"> | ||
118 | level_div = document.createElement("div"); | ||
119 | level_div.classList.add("level"); | ||
120 | previous_element.appendChild(level_div); | ||
121 | } | ||
122 | |||
123 | // déplacement | ||
124 | level_div.appendChild(element); | ||
125 | |||
126 | // marges | ||
127 | let margin_left = parseInt(element.style.marginLeft); | ||
128 | margin_left += 29; | ||
129 | element.style.marginLeft = String(margin_left) + "px"; | ||
130 | |||
131 | // MAJ des chemins affichés si c'est un chemin relatif (les liens URL ne peuvent avoir d'enfants) | ||
132 | const element_path = element.querySelector(".path"); | ||
133 | if(element_path != null){ | ||
134 | const previous_element_path = previous_element.querySelector(".path"); | ||
135 | element_path.innerHTML = previous_element_path.innerHTML + "/" + element_path.innerHTML.split("/").slice(-1); | ||
136 | |||
137 | // même chose pour tous les enfants sauf les URL vers l'extérieur | ||
138 | if(element.querySelector(".level") != null){ | ||
139 | element.querySelector(".level").querySelectorAll(".path").forEach( (one_elem) => { | ||
140 | const parent_elem_path = one_elem.parentNode.parentNode.parentNode.querySelector(".path"); // => div de l'élém => div class level => div du parent | ||
141 | const end_of_path = one_elem.innerHTML.split("/").slice(-1); | ||
142 | one_elem.innerHTML = parent_elem_path.innerHTML + "/" + end_of_path[0]; | ||
143 | }); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | // dernier problème à corriger: le parent est une URL vers l'extérieur | ||
148 | } | ||
149 | else{ | ||
150 | // ne rien faire | ||
151 | console.log("pas d'élément précédent"); | ||
152 | }*/ | ||
153 | } | ||
154 | |||
155 | function switchMenuPositions(page_id, direction) | ||
156 | { | ||
157 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
158 | const clicked_menu_entry = document.getElementById(page_id); // div parente du bouton | ||
159 | let other_entry = null; | ||
160 | |||
161 | // pas bon | ||
162 | if(direction == 'down'){ | ||
163 | other_entry = clicked_menu_entry.nextElementSibling; | ||
164 | } | ||
165 | else if(direction == 'up'){ | ||
166 | other_entry = clicked_menu_entry.previousElementSibling; | ||
167 | } | ||
168 | |||
169 | if(other_entry == null){ | ||
170 | console.log('Inversion impossible'); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | fetch('index.php?menu_edit=switch_positions', { | ||
175 | method: 'POST', | ||
176 | headers: { | ||
177 | 'Content-Type': 'application/json' | ||
178 | }, | ||
179 | body: JSON.stringify({ id1: clicked_menu_entry.id, id2: other_entry.id }) | ||
180 | }) | ||
181 | .then(response => response.json()) | ||
182 | .then(data => { | ||
183 | if(data.success) | ||
184 | { | ||
185 | if(direction == 'down'){ | ||
186 | clicked_menu_entry.parentElement.insertBefore(other_entry, clicked_menu_entry); | ||
187 | } | ||
188 | else if(direction == 'up'){ | ||
189 | other_entry.parentElement.insertBefore(clicked_menu_entry, other_entry); | ||
190 | } | ||
191 | else{ | ||
192 | console.error('Échec de l\'inversion'); | ||
193 | } | ||
194 | |||
195 | // menu régénéré | ||
196 | nav_zone.innerHTML = ''; | ||
197 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
198 | } | ||
199 | else { | ||
200 | |||
201 | console.error('Échec de l\'inversion'); | ||
202 | } | ||
203 | }) | ||
204 | .catch(error => { | ||
205 | console.error('Erreur:', error); | ||
206 | }); | ||
207 | } | ||
208 | |||
209 | function checkMenuEntry(page_id){ | ||
210 | const nav_zone = document.getElementById("nav_zone"); // parent de <nav> | ||
211 | const clicked_menu_entry = document.getElementById(page_id); // div parente du bouton | ||
212 | const checkbox = clicked_menu_entry.querySelector("input"); | ||
213 | let color; | ||
214 | |||
215 | fetch('index.php?menu_edit=displayInMenu', { | ||
216 | method: 'POST', | ||
217 | headers: { | ||
218 | 'Content-Type': 'application/json' | ||
219 | }, | ||
220 | body: JSON.stringify({ id: clicked_menu_entry.id, checked: checkbox.checked }) | ||
221 | }) | ||
222 | .then(response => response.json()) | ||
223 | .then(data => { | ||
224 | if(data.success) | ||
225 | { | ||
226 | color = checkbox.checked ? "#ff1d04" : "grey"; | ||
227 | clicked_menu_entry.querySelector("button").style.color = color; | ||
228 | |||
229 | nav_zone.innerHTML = ''; | ||
230 | nav_zone.insertAdjacentHTML('afterbegin', data.nav); | ||
231 | } | ||
232 | else { | ||
233 | |||
234 | console.error('Échec de l\'inversion'); | ||
235 | } | ||
236 | }) | ||
237 | .catch(error => { | ||
238 | console.error('Erreur:', error); | ||
239 | }); | ||
240 | } \ No newline at end of file | ||
diff --git a/src/controller/ajax.php b/src/controller/ajax.php index 9d1cc42..a20bd87 100644 --- a/src/controller/ajax.php +++ b/src/controller/ajax.php | |||
@@ -170,7 +170,8 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) | |||
170 | } | 170 | } |
171 | 171 | ||
172 | // détection des requêtes d'upload d'image de tinymce | 172 | // détection des requêtes d'upload d'image de tinymce |
173 | if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image'){ | 173 | if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image') |
174 | { | ||
174 | if (isset($_FILES['file'])) { | 175 | if (isset($_FILES['file'])) { |
175 | $file = $_FILES['file']; | 176 | $file = $_FILES['file']; |
176 | $dest = 'images/'; | 177 | $dest = 'images/'; |
@@ -211,6 +212,90 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['menu_edit'])) | |||
211 | $json = json_decode($data, true); | 212 | $json = json_decode($data, true); |
212 | Director::$menu_data = new Menu($entityManager); | 213 | Director::$menu_data = new Menu($entityManager); |
213 | 214 | ||
215 | // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions | ||
216 | if($_GET['menu_edit'] === 'move_one_level_up' && isset($json['id'])){ | ||
217 | $id = $json['id']; | ||
218 | $page = Director::$menu_data->findPageById((int)$id); | ||
219 | |||
220 | $parent = $page->getParent(); // peut être null | ||
221 | if($parent === null){ | ||
222 | // 1er niveau: ne rien faire | ||
223 | echo json_encode(['success' => false]); | ||
224 | die; | ||
225 | } | ||
226 | // BDD | ||
227 | else{ | ||
228 | $page->setPosition($parent->getPosition() + 1); // nouvelle position | ||
229 | |||
230 | // 2ème niveau: le parent devient $menu_data, puis null après tri | ||
231 | if($parent->getParent() === null){ | ||
232 | // connexion dans les deux sens | ||
233 | $page->setParent(Director::$menu_data); // => pour la persistance | ||
234 | |||
235 | //Director::$menu_data->addChild($page); // => pour sortChildren | ||
236 | $page->getParent()->addChild($page); // => pour sortChildren | ||
237 | //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
238 | $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
239 | $page->setParent(null); | ||
240 | |||
241 | // affichage | ||
242 | $page->setPagePath($page->getEndOfPath()); | ||
243 | $page->fillChildrenPagePath(); | ||
244 | } | ||
245 | // 3ème niveau et plus | ||
246 | else{ | ||
247 | $page->setParent($parent->getParent()); // nouveau parent | ||
248 | $page->getParent()->addChild($page); // => pour sortChildren | ||
249 | $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
250 | $page->fillChildrenPagePath($page->getParent()->getPagePath()); | ||
251 | } | ||
252 | //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive? | ||
253 | $entityManager->flush(); | ||
254 | |||
255 | // affichage | ||
256 | $parent->removeChild($page); | ||
257 | $nav_builder = new NavBuilder(); | ||
258 | $menu_builder = new MenuBuilder(null, false); | ||
259 | echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); | ||
260 | die; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | // flèche droite =>: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent | ||
265 | if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){ | ||
266 | $id = $json['id']; | ||
267 | $page = Director::$menu_data->findPageById((int)$id); | ||
268 | |||
269 | $parent = $page->getParent(); // peut être null | ||
270 | if($parent == null){ | ||
271 | $parent = Director::$menu_data; | ||
272 | } | ||
273 | |||
274 | // BDD | ||
275 | $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3... | ||
276 | if($page->getPosition() > 1){ | ||
277 | foreach($parent->getChildren() as $child){ | ||
278 | //echo $child->getPageName(); | ||
279 | if($child->getPosition() === $page->getPosition() - 1){ | ||
280 | $page->setParent($child); | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | $page->setPosition(count($page->getParent()->getChildren()) + 1); | ||
285 | } | ||
286 | $entityManager->flush(); | ||
287 | |||
288 | // affichage | ||
289 | $parent->removeChild($page); | ||
290 | $page->getParent()->addChild($page); | ||
291 | $page->fillChildrenPagePath($page->getParent()->getPagePath()); // variable non mappée $page_path | ||
292 | $nav_builder = new NavBuilder(); | ||
293 | $menu_builder = new MenuBuilder(null, false); | ||
294 | |||
295 | echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); | ||
296 | die; | ||
297 | } | ||
298 | |||
214 | if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) | 299 | if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) |
215 | { | 300 | { |
216 | $id1 = $json['id1']; | 301 | $id1 = $json['id1']; |
diff --git a/src/controller/installation.php b/src/controller/installation.php index ff168eb..4aaa4e0 100644 --- a/src/controller/installation.php +++ b/src/controller/installation.php | |||
@@ -77,12 +77,12 @@ HTACCESS; | |||
77 | function makeStartPage(EntityManager $entityManager){ | 77 | function makeStartPage(EntityManager $entityManager){ |
78 | /* -- table page -- */ | 78 | /* -- table page -- */ |
79 | // paramètres: name_page, end_of_path, reachable, in_menu, position, parent | 79 | // paramètres: name_page, end_of_path, reachable, in_menu, position, parent |
80 | $accueil = new Page('Accueil', 'accueil', true, true, 1, NULL); | 80 | $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL); |
81 | $connection = new Page('Connexion', 'connexion', true, false, NULL, NULL); | 81 | $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); |
82 | $article = new Page('Article', 'article', true, false, NULL, NULL); | 82 | $article = new Page('Article', 'article', true, false, false, NULL, NULL); |
83 | $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, NULL, NULL); | 83 | $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL); |
84 | $edit_page = new Page("Modification d'une page", 'modif_page', true, false, NULL, NULL); | 84 | $edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); |
85 | $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, NULL, NULL); | 85 | $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL); |
86 | 86 | ||
87 | /* -- table node -- */ | 87 | /* -- table node -- */ |
88 | // paramètres: name_node, article_timestamp, attributes, position, parent, page, article | 88 | // paramètres: name_node, article_timestamp, attributes, position, parent, page, article |
@@ -95,7 +95,7 @@ function makeStartPage(EntityManager $entityManager){ | |||
95 | $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav', 'main'], 'js_array' => ['main']], 1, NULL, $connection, NULL); | 95 | $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav', 'main'], 'js_array' => ['main']], 1, NULL, $connection, NULL); |
96 | $login = new Node('login', NULL, [], 1, $main, $connection, NULL); | 96 | $login = new Node('login', NULL, [], 1, $main, $connection, NULL); |
97 | $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); | 97 | $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); |
98 | $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'menu'], 'js_array' => ['main']], 1, NULL, $menu_paths, NULL); | 98 | $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'menu'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); |
99 | $edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); | 99 | $edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); |
100 | 100 | ||
101 | /* -- table image -- */ | 101 | /* -- table image -- */ |
diff --git a/src/controller/post.php b/src/controller/post.php index 926a5ae..8924686 100644 --- a/src/controller/post.php +++ b/src/controller/post.php | |||
@@ -5,13 +5,89 @@ declare(strict_types=1); | |||
5 | 5 | ||
6 | if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) | 6 | if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) |
7 | { | 7 | { |
8 | // requêtes AJAX | 8 | /* -- requêtes non AJAX -- */ |
9 | // page Menu et chemin | ||
10 | /*if(isset($_POST['menu_edit_post']) && isset($_POST['id'])) | ||
11 | { | ||
12 | // <= flèche gauche: le parent devient le grand-parent position = position du parent + 1, recalculer les positions des enfants restants | ||
13 | if($_POST['menu_edit_post'] == 'move_one_level_up'){ | ||
14 | Director::$menu_data = new Menu($entityManager); | ||
15 | $page = Director::$menu_data->findPageById((int)$_POST['id']); | ||
16 | |||
17 | $parent = $page->getParent(); // peut être null | ||
18 | if($parent === null){ | ||
19 | // 1er niveau: ne rien faire | ||
20 | header('Location: ' . new URL(['page' => 'menu_chemins'])); | ||
21 | die; | ||
22 | } | ||
23 | else{ | ||
24 | $page->setPosition($parent->getPosition() + 1); // nouvelle position | ||
25 | |||
26 | // 2ème niveau: le parent devient $menu_data, puis null après tri | ||
27 | if($parent->getParent() === null){ | ||
28 | // connexion dans les deux sens | ||
29 | $page->setParent(Director::$menu_data); // => pour la persistance | ||
30 | Director::$menu_data->addChild($page); // => pour sortChildren | ||
31 | |||
32 | //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
33 | $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
34 | |||
35 | $page->setParent(null); | ||
36 | } | ||
37 | // 3ème niveau et plus | ||
38 | else{ | ||
39 | $page->setParent($parent->getParent()); // nouveau parent | ||
40 | $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères | ||
41 | } | ||
42 | //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive? | ||
43 | echo $page->getPosition(); | ||
44 | //die; | ||
45 | } | ||
46 | $entityManager->flush(); | ||
47 | |||
48 | header('Location: ' . new URL(['page' => 'menu_chemins'])); | ||
49 | die; | ||
50 | } | ||
51 | // => flèche droite: l'élément précédent devient le parent, position = nombre d'éléments de la fraterie + 1 | ||
52 | elseif($_POST['menu_edit_post'] == 'move_one_level_down') | ||
53 | { | ||
54 | Director::$menu_data = new Menu($entityManager); | ||
55 | $page = Director::$menu_data->findPageById((int)$_POST['id']); | ||
56 | |||
57 | $parent = $page->getParent(); // peut être null | ||
58 | if($parent == null){ | ||
59 | $parent = Director::$menu_data; | ||
60 | } | ||
61 | |||
62 | $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3... | ||
63 | if($page->getPosition() > 1){ | ||
64 | foreach($parent->getChildren() as $child){ | ||
65 | echo $child->getPageName(); | ||
66 | if($child->getPosition() === $page->getPosition() - 1){ | ||
67 | $page->setParent($child); | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | $page->setPosition(count($page->getParent()->getChildren()) + 1); | ||
72 | } | ||
73 | $entityManager->flush(); | ||
74 | |||
75 | header('Location: ' . new URL(['page' => 'menu_chemins'])); | ||
76 | die; | ||
77 | } | ||
78 | else{ | ||
79 | // you talking to me? | ||
80 | die; | ||
81 | } | ||
82 | }*/ | ||
83 | |||
84 | /* -- requêtes AJAX -- */ | ||
9 | require '../src/controller/ajax.php'; | 85 | require '../src/controller/ajax.php'; |
10 | 86 | ||
11 | // formulaires HTML | 87 | // formulaires HTML |
12 | if(isset($_POST['from']) // page d'où vient la requête | 88 | /*if(isset($_POST['from']) // page d'où vient la requête |
13 | && isset($_POST)) // données | 89 | && isset($_POST)) // données |
14 | { | 90 | { |
15 | echo "requête envoyée en validant un formulaire"; | 91 | echo "requête envoyée en validant un formulaire"; |
16 | } | 92 | }*/ |
17 | } | 93 | } |
diff --git a/src/model/Position.php b/src/model/Position.php index 74d173a..76de966 100644 --- a/src/model/Position.php +++ b/src/model/Position.php | |||
@@ -7,34 +7,30 @@ declare(strict_types=1); | |||
7 | 7 | ||
8 | trait Position | 8 | trait Position |
9 | { | 9 | { |
10 | public function sortChildren(bool $reposition = false): void | 10 | public function sortChildren(bool $reindexation = false): void |
11 | { | 11 | { |
12 | // ordre du tableau des enfants | 12 | // tri par insertion du tableau des enfants |
13 | // inefficace quand des noeuds ont la même position | ||
14 | |||
15 | // tri par insertion avant affichage | ||
16 | for($i = 1; $i < count($this->children); $i++) | 13 | for($i = 1; $i < count($this->children); $i++) |
17 | { | 14 | { |
18 | $tmp = $this->children[$i]; | 15 | $tmp = $this->children[$i]; |
19 | $j = $i - 1; | 16 | $j = $i - 1; |
20 | 17 | ||
21 | // Déplacez les éléments du tableau qui sont plus grands que la clé | 18 | // Déplacez les éléments du tableau qui sont plus grands que la clé à une position devant leur position actuelle |
22 | // à une position devant leur position actuelle | 19 | while($j >= 0 && $this->children[$j]->getPosition() > $tmp->getPosition()) { |
23 | while ($j >= 0 && $this->children[$j]->getPosition() > $tmp->getPosition()) { | ||
24 | $this->children[$j + 1] = $this->children[$j]; | 20 | $this->children[$j + 1] = $this->children[$j]; |
25 | $j = $j - 1; | 21 | $j--; |
26 | } | 22 | } |
27 | $this->children[$j + 1] = $tmp; | 23 | $this->children[$j + 1] = $tmp; |
28 | } | 24 | } |
29 | 25 | ||
30 | foreach ($this->children as $child) { | 26 | foreach($this->children as $child) { |
31 | if (count($child->children) > 0) { | 27 | if(count($child->children) > 0) { |
32 | $child->sortChildren($reposition); | 28 | $child->sortChildren($reindexation); |
33 | } | 29 | } |
34 | } | 30 | } |
35 | 31 | ||
36 | // nouvelles positions (tableau $children => BDD) | 32 | // nouvelles positions (tableau $children => BDD) |
37 | if($reposition){ | 33 | if($reindexation){ |
38 | $i = 1; | 34 | $i = 1; |
39 | foreach($this->children as $child){ | 35 | foreach($this->children as $child){ |
40 | $child->setPosition($i); | 36 | $child->setPosition($i); |
diff --git a/src/model/entities/Page.php b/src/model/entities/Page.php index e3e60ca..aaff1ff 100644 --- a/src/model/entities/Page.php +++ b/src/model/entities/Page.php | |||
@@ -75,6 +75,10 @@ class Page | |||
75 | { | 75 | { |
76 | return $this->page_path; | 76 | return $this->page_path; |
77 | } | 77 | } |
78 | public function setPagePath(string $path):void | ||
79 | { | ||
80 | $this->page_path = $path; | ||
81 | } | ||
78 | public function getEndOfPath(): string | 82 | public function getEndOfPath(): string |
79 | { | 83 | { |
80 | return $this->end_of_path; | 84 | return $this->end_of_path; |
@@ -107,6 +111,10 @@ class Page | |||
107 | { | 111 | { |
108 | return $this->parent; | 112 | return $this->parent; |
109 | } | 113 | } |
114 | public function setParent(?Page $parent): void | ||
115 | { | ||
116 | $this->parent = $parent; | ||
117 | } | ||
110 | public function getChildren(): Collection | 118 | public function getChildren(): Collection |
111 | { | 119 | { |
112 | return $this->children; | 120 | return $this->children; |
@@ -125,6 +133,14 @@ class Page | |||
125 | $this->children[] = $child; | 133 | $this->children[] = $child; |
126 | $this->sortChildren(false); | 134 | $this->sortChildren(false); |
127 | } | 135 | } |
136 | public function removeChild(self $child): void | ||
137 | { | ||
138 | foreach($this->children as $index => $candidate){ | ||
139 | if($candidate === $child){ | ||
140 | unset($this->children[$index]); | ||
141 | } | ||
142 | } | ||
143 | } | ||
128 | 144 | ||
129 | public function findPageById(int $id): ?Page | 145 | public function findPageById(int $id): ?Page |
130 | { | 146 | { |
diff --git a/src/view/MenuBuilder.php b/src/view/MenuBuilder.php index 5a010d5..42c9273 100644 --- a/src/view/MenuBuilder.php +++ b/src/view/MenuBuilder.php | |||
@@ -1,19 +1,19 @@ | |||
1 | <?php | 1 | <?php |
2 | // src/view/MenuBuilder.php | 2 | // src/view/MenuBuilder.php |
3 | // | 3 | // |
4 | // page Menu et chemins en mode admin | 4 | // page Menu et chemins en mode admin, fonctionne avec menu.js |
5 | 5 | ||
6 | use App\Entity\Node; | 6 | use App\Entity\Node; |
7 | use App\Entity\Page; | 7 | use App\Entity\Page; |
8 | 8 | ||
9 | class MenuBuilder extends AbstractBuilder | 9 | class MenuBuilder extends AbstractBuilder |
10 | { | 10 | { |
11 | private int $margin_left_multiplier = 29; | 11 | //private int $margin_left_multiplier = 29; |
12 | 12 | ||
13 | public function __construct(Node $node) | 13 | public function __construct(Node $node = null, bool $template = true) |
14 | { | 14 | { |
15 | parent::__construct($node); | 15 | //parent::__construct($node); |
16 | $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; | 16 | $viewFile = $node === null ? self::VIEWS_PATH . 'menu.php' : self::VIEWS_PATH . $node->getName() . '.php'; |
17 | 17 | ||
18 | if(file_exists($viewFile)) | 18 | if(file_exists($viewFile)) |
19 | { | 19 | { |
@@ -22,33 +22,33 @@ class MenuBuilder extends AbstractBuilder | |||
22 | extract($node->getNodeData()->getData()); | 22 | extract($node->getNodeData()->getData()); |
23 | }*/ | 23 | }*/ |
24 | 24 | ||
25 | if($_SESSION['admin']) | 25 | if($_SESSION['admin']){ |
26 | { | 26 | $this->unfoldMenu(Director::$menu_data/*, 0 - $this->margin_left_multiplier*/); |
27 | $this->unfoldMenu(Director::$menu_data, 0 - $this->margin_left_multiplier); | ||
28 | } | 27 | } |
29 | else{ | 28 | else{ |
30 | header('Location: ' . new URL); | 29 | header('Location: ' . new URL); |
31 | die; | 30 | die; |
32 | } | 31 | } |
33 | 32 | ||
34 | ob_start(); | 33 | // si faux, n'utilise pas le template |
35 | require $viewFile; | 34 | if($template){ |
36 | $this->html = ob_get_clean(); // pas de concaténation ici, on écrase | 35 | ob_start(); |
36 | require $viewFile; // insertion de $this->html généré par unfoldMenu | ||
37 | $this->html = ob_get_clean(); // pas de concaténation .= cette fois on écrase | ||
38 | } | ||
37 | } | 39 | } |
38 | } | 40 | } |
39 | 41 | ||
40 | private function unfoldMenu(Page $menu, int $margin_left): void | 42 | private function unfoldMenu(Page $menu): void |
41 | { | 43 | { |
42 | $margin_left += $this->margin_left_multiplier; | ||
43 | $this->html .= '<div class="level">' . "\n"; | 44 | $this->html .= '<div class="level">' . "\n"; |
44 | 45 | ||
45 | foreach($menu->getChildren() as $entry) | 46 | foreach($menu->getChildren() as $entry) |
46 | { | 47 | { |
47 | $div_style = 'margin-left: ' . $margin_left . 'px;'; | ||
48 | $checked = $entry->isHidden() ? '' : 'checked'; | 48 | $checked = $entry->isHidden() ? '' : 'checked'; |
49 | $this->html .= '<div id="' . $entry->getId() . '" style="' . $div_style . '"> | 49 | $this->html .= '<div id="' . $entry->getId() . '" class="menu_edit_entry"> |
50 | <img class="move_entry_icon" onclick="" src="assets/arrow-left.svg"> | 50 | <img class="move_entry_icon" onclick="moveOneLevelUp(' . $entry->getId() . ')" src="assets/arrow-left.svg"> |
51 | <img class="move_entry_icon" onclick="" src="assets/arrow-right.svg"> | 51 | <img class="move_entry_icon" onclick="moveOneLevelDown(' . $entry->getId() . ')" src="assets/arrow-right.svg"> |
52 | <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'up\')" src="assets/arrow-up.svg"> | 52 | <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'up\')" src="assets/arrow-up.svg"> |
53 | <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'down\')" src="assets/arrow-down.svg"> | 53 | <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'down\')" src="assets/arrow-down.svg"> |
54 | <span class="menu_entry_checkbox"> | 54 | <span class="menu_entry_checkbox"> |
@@ -58,24 +58,18 @@ class MenuBuilder extends AbstractBuilder | |||
58 | 58 | ||
59 | if(str_starts_with($entry->getEndOfPath(), 'http')){ | 59 | if(str_starts_with($entry->getEndOfPath(), 'http')){ |
60 | $this->html .= '<span id="edit-i..."><img class="move_entry_icon" src="assets/edit.svg" onclick="openEditor(\'i...\')"></span> | 60 | $this->html .= '<span id="edit-i..."><img class="move_entry_icon" src="assets/edit.svg" onclick="openEditor(\'i...\')"></span> |
61 | <i>' . $entry->getEndOfPath() . '</i> | 61 | <i class="url">' . $entry->getEndOfPath() . '</i> |
62 | <span id="delete-i..."><img class="move_entry_icon" src="assets/delete-bin.svg" onclick="delete(\'i...\')"></span>'; | 62 | <span id="delete-i..."><img class="move_entry_icon" src="assets/delete-bin.svg" onclick="delete(\'i...\')"></span>'; |
63 | } | 63 | } |
64 | else{ | 64 | else{ |
65 | $this->html .= '<i>' . $entry->getPagePath() . '</i>'; | 65 | $this->html .= '<i class="path">' . $entry->getPagePath() . '</i>'; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | ||
69 | => flèche gauche: position = position du parent + 1, parent = grand-parent, recalculer les positions | ||
70 | => flèche droite: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent | ||
71 | */ | ||
72 | |||
73 | if(count($entry->getChildren()) > 0){ | 68 | if(count($entry->getChildren()) > 0){ |
74 | $this->unfoldMenu($entry, $margin_left); | 69 | $this->unfoldMenu($entry); |
75 | } | 70 | } |
76 | $this->html .= '</div>' . "\n"; | 71 | $this->html .= '</div>' . "\n"; |
77 | } | 72 | } |
78 | $this->html .= "</div>\n"; | 73 | $this->html .= "</div>\n"; |
79 | $margin_left -= $this->margin_left_multiplier; | ||
80 | } | 74 | } |
81 | } \ No newline at end of file | 75 | } \ No newline at end of file |
diff --git a/src/view/templates/menu.php b/src/view/templates/menu.php index a7f318e..1414ab0 100644 --- a/src/view/templates/menu.php +++ b/src/view/templates/menu.php | |||
@@ -6,10 +6,13 @@ | |||
6 | <p><img src="assets/arrow-up.svg"><img src="assets/arrow-down.svg"> déplacer la branche parmi celles de même niveau</p> | 6 | <p><img src="assets/arrow-up.svg"><img src="assets/arrow-down.svg"> déplacer la branche parmi celles de même niveau</p> |
7 | <p><input type="checkbox" checked>afficher/cacher</p> | 7 | <p><input type="checkbox" checked>afficher/cacher</p> |
8 | </aside> | 8 | </aside> |
9 | <div id="menu_edit_buttons"> | ||
9 | <?= $this->html ?> | 10 | <?= $this->html ?> |
11 | </div> | ||
10 | <div class="new_entry_buttons"> | 12 | <div class="new_entry_buttons"> |
11 | <p>Ajouter une nouvelle entrée dans le menu?</p> | 13 | <p>Ajouter une nouvelle entrée dans le menu |
12 | <button id="new-i..." onclick="openEditor('i...')"><img class="action_icon" src="assets/edit.svg">avec une URL</button> | 14 | <button id="new-i..." onclick="openEditor('i...')"><img class="action_icon" src="assets/edit.svg">avec une URL</button> |
13 | ...sinon cliquer sur Nouvelle page<img src="assets/arrow-down.svg">dans la barre jaune | 15 | ?</p> |
16 | <p>... ou cliquer sur <span style="color: #ff1d04;">Nouvelle page</span><img src="assets/arrow-down.svg">dans la barre jaune</p> | ||
14 | </div> | 17 | </div> |
15 | </section> \ No newline at end of file | 18 | </section> \ No newline at end of file |