summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-04-27 23:58:46 +0200
committerpolo <ordipolo@gmx.fr>2025-04-27 23:58:46 +0200
commit962d315ec0c99974df3dc2261bf94c54ca8cdbdd (patch)
tree7463f74a722e759067daf8c3ef43202a60352759
parenta3ba7dde60dc1c94b7170ec28266a966e5004d33 (diff)
downloadcms-962d315ec0c99974df3dc2261bf94c54ca8cdbdd.zip
page menu et chemins, partie3
-rw-r--r--public/css/menu.css14
-rw-r--r--public/js/main.js93
-rw-r--r--public/js/menu.js240
-rw-r--r--src/controller/ajax.php87
-rw-r--r--src/controller/installation.php14
-rw-r--r--src/controller/post.php82
-rw-r--r--src/model/Position.php22
-rw-r--r--src/model/entities/Page.php16
-rw-r--r--src/view/MenuBuilder.php46
-rw-r--r--src/view/templates/menu.php9
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 */
209function moveOneLevelUp(){}
210function moveOneLevelDown(){}
211
212function 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
267function 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
2function 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
36function 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
155function 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
209function 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
173if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image'){ 173if(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;
77function makeStartPage(EntityManager $entityManager){ 77function 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
6if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) 6if($_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
8trait Position 8trait 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
6use App\Entity\Node; 6use App\Entity\Node;
7use App\Entity\Page; 7use App\Entity\Page;
8 8
9class MenuBuilder extends AbstractBuilder 9class 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