diff options
| author | polo <ordipolo@gmx.fr> | 2025-10-09 01:35:52 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2025-10-09 01:35:52 +0200 |
| commit | 15cbf5d56b4644151d59fee512f5f8fbe496caa3 (patch) | |
| tree | 0da411f4aff53a0249cf3d59ea13f3786897b740 | |
| parent | 9f88389d78755d7c69c29e9db8f114fd1dbef034 (diff) | |
| download | cms-15cbf5d56b4644151d59fee512f5f8fbe496caa3.tar.gz cms-15cbf5d56b4644151d59fee512f5f8fbe496caa3.tar.bz2 cms-15cbf5d56b4644151d59fee512f5f8fbe496caa3.zip | |
pagination partie 2, nouvelles fonctions + renommage dans Director, ArticleController::fetch, et en JS: fetchArticles, insertLocalDates, modifs dans changePaginationLimit, dans les vues
| -rw-r--r-- | public/css/body.css | 8 | ||||
| -rw-r--r-- | public/js/main.js | 57 | ||||
| -rw-r--r-- | public/js/modif_page.js | 78 | ||||
| -rw-r--r-- | public/js/tinymce.js | 28 | ||||
| -rw-r--r-- | src/controller/ArticleController.php | 41 | ||||
| -rw-r--r-- | src/controller/Director.php | 132 | ||||
| -rw-r--r-- | src/controller/PageManagementController.php | 17 | ||||
| -rw-r--r-- | src/model/entities/NodeData.php | 17 | ||||
| -rw-r--r-- | src/router.php | 31 | ||||
| -rw-r--r-- | src/view/AbstractBuilder.php | 4 | ||||
| -rw-r--r-- | src/view/NewBuilder.php | 6 | ||||
| -rw-r--r-- | src/view/NewsBlockBuilder.php | 3 | ||||
| -rw-r--r-- | src/view/PostBlockBuilder.php | 1 | ||||
| -rw-r--r-- | src/view/templates/modify_block.php | 7 | ||||
| -rw-r--r-- | src/view/templates/news_block.php | 5 | ||||
| -rw-r--r-- | src/view/templates/post_block.php | 5 |
16 files changed, 332 insertions, 108 deletions
diff --git a/public/css/body.css b/public/css/body.css index 140655b..b728d05 100644 --- a/public/css/body.css +++ b/public/css/body.css | |||
| @@ -49,12 +49,20 @@ main | |||
| 49 | { | 49 | { |
| 50 | display: none; | 50 | display: none; |
| 51 | } | 51 | } |
| 52 | section | ||
| 53 | { | ||
| 54 | margin: 10px 0; | ||
| 55 | } | ||
| 52 | section > h3 | 56 | section > h3 |
| 53 | { | 57 | { |
| 54 | padding: 15px; | 58 | padding: 15px; |
| 55 | margin: 0; | 59 | margin: 0; |
| 56 | text-align: center; | 60 | text-align: center; |
| 57 | } | 61 | } |
| 62 | section .fetch_articles | ||
| 63 | { | ||
| 64 | margin-left: 15px; | ||
| 65 | } | ||
| 58 | .login_form | 66 | .login_form |
| 59 | { | 67 | { |
| 60 | background-color: white; | 68 | background-color: white; |
diff --git a/public/js/main.js b/public/js/main.js index d2f8876..59a9331 100644 --- a/public/js/main.js +++ b/public/js/main.js | |||
| @@ -36,15 +36,10 @@ function toastNotify(message){ | |||
| 36 | setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000); | 36 | setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | |||
| 40 | // exécuté à la fin du chargement de la page | 39 | // exécuté à la fin du chargement de la page |
| 41 | document.addEventListener('DOMContentLoaded', () => { | 40 | document.addEventListener('DOMContentLoaded', () => { |
| 42 | 41 | ||
| 43 | // détection des dates et conversion à l'heure locale | 42 | insertLocalDates(); |
| 44 | document.querySelectorAll('.local_date').forEach(function(element){ | ||
| 45 | const utc_date = element.getAttribute('date-utc'); // forme: 2025-10-10T12:17:00+00:00 | ||
| 46 | element.innerText = toFormatedLocalDate(utc_date); | ||
| 47 | }); | ||
| 48 | 43 | ||
| 49 | // ouvrir/fermer les sous-menus avec écran tactile | 44 | // ouvrir/fermer les sous-menus avec écran tactile |
| 50 | document.querySelectorAll('.sub-menu-toggle').forEach(button => { | 45 | document.querySelectorAll('.sub-menu-toggle').forEach(button => { |
| @@ -85,6 +80,48 @@ document.addEventListener('DOMContentLoaded', () => { | |||
| 85 | }); | 80 | }); |
| 86 | 81 | ||
| 87 | 82 | ||
| 83 | function fetchArticles(bloc_id){ | ||
| 84 | const parent = document.getElementById(bloc_id); | ||
| 85 | |||
| 86 | const block_type = parent.getAttribute('block-type'); | ||
| 87 | let last_article = ''; | ||
| 88 | if(block_type === 'post_block'){ | ||
| 89 | // pas parfait, suppose que les positions sont correctes | ||
| 90 | last_article = parent.querySelectorAll('article').length - 1; | ||
| 91 | } | ||
| 92 | else if(block_type === 'news_block'){ | ||
| 93 | // date_time du dernier article affiché (heure UTC), date vide si bloc vide | ||
| 94 | const news_elements = parent.querySelector('.section_child').querySelectorAll('article'); | ||
| 95 | last_article = news_elements.length !== 0 ? news_elements[news_elements.length - 1].querySelector('.local_date').getAttribute('date-utc') : ''; | ||
| 96 | } | ||
| 97 | else{ | ||
| 98 | console.log("Erreur, le type de bloc n'est pas reconnu"); | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | fetch('index.php?fetch=next_articles&id=' + bloc_id + '&last_article=' + last_article) // méthode GET par défaut | ||
| 103 | .then(response => response.json()) | ||
| 104 | .then(data => { | ||
| 105 | if(data.success){ | ||
| 106 | // insérer les articles | ||
| 107 | parent.querySelector('.section_child').innerHTML += data.html; | ||
| 108 | insertLocalDates(); | ||
| 109 | |||
| 110 | // cacher le bouton | ||
| 111 | parent.querySelector('.fetch_articles').querySelector('button').className = data.truncated ? '' : 'hidden'; | ||
| 112 | |||
| 113 | console.log("Articles insérés dans le bloc"); | ||
| 114 | } | ||
| 115 | else{ | ||
| 116 | console.log("Erreur côté serveur à la récupération d'articles"); | ||
| 117 | } | ||
| 118 | }) | ||
| 119 | .catch(error => { | ||
| 120 | console.error('Erreur:', error); | ||
| 121 | }); | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 88 | // complète les fonctions dans tinymce.js | 125 | // complète les fonctions dans tinymce.js |
| 89 | function switchPositions(article_id, direction) | 126 | function switchPositions(article_id, direction) |
| 90 | { | 127 | { |
| @@ -239,6 +276,14 @@ function submitDate(id_date) | |||
| 239 | } | 276 | } |
| 240 | } | 277 | } |
| 241 | 278 | ||
| 279 | function insertLocalDates(){ | ||
| 280 | // détection des dates et conversion à l'heure locale | ||
| 281 | document.querySelectorAll('.local_date').forEach(function(element){ | ||
| 282 | const utc_date = element.getAttribute('date-utc'); // forme: 2025-10-10T12:17:00+00:00 | ||
| 283 | element.innerText = toFormatedLocalDate(utc_date); | ||
| 284 | }); | ||
| 285 | } | ||
| 286 | |||
| 242 | function toFormatedLocalDate(utc_string_date){ // forme: 2025-07-17T13:54:00.000Z ou 2025-02-04T00:24 | 287 | function toFormatedLocalDate(utc_string_date){ // forme: 2025-07-17T13:54:00.000Z ou 2025-02-04T00:24 |
| 243 | const date = new Date(utc_string_date); | 288 | const date = new Date(utc_string_date); |
| 244 | 289 | ||
diff --git a/public/js/modif_page.js b/public/js/modif_page.js index bf269ee..15f3598 100644 --- a/public/js/modif_page.js +++ b/public/js/modif_page.js | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | /* -- mode modification d'une page -- */ | 1 | /* -- mode modification d'une page -- */ |
| 2 | 2 | ||
| 3 | // beaucoup de fonctions similaires | ||
| 4 | // à factoriser avec le pattern stratégie? | ||
| 5 | |||
| 3 | // même fonction que dans new_page.js | 6 | // même fonction que dans new_page.js |
| 4 | function makePageNamePath(){ | 7 | function makePageNamePath(){ |
| 5 | document.getElementById("page_name_path").value = document.getElementById("page_name").value | 8 | document.getElementById("page_name_path").value = document.getElementById("page_name").value |
| @@ -92,7 +95,7 @@ function changeDescription(node_data_id){ | |||
| 92 | toastNotify("la nouvelle description de la page est: " + data.description); | 95 | toastNotify("la nouvelle description de la page est: " + data.description); |
| 93 | } | 96 | } |
| 94 | else{ | 97 | else{ |
| 95 | console.error('Erreur à la modification de la description de la page.'); | 98 | console.error('Erreur côté serveur à la modification de la description de la page.'); |
| 96 | } | 99 | } |
| 97 | }) | 100 | }) |
| 98 | .catch(error => { | 101 | .catch(error => { |
| @@ -119,7 +122,7 @@ function renamePageBloc(bloc_id){ | |||
| 119 | toastNotify('Le bloc a été renommé: ' + data.title); | 122 | toastNotify('Le bloc a été renommé: ' + data.title); |
| 120 | } | 123 | } |
| 121 | else{ | 124 | else{ |
| 122 | console.error('Erreur au renommage du titre.'); | 125 | console.error('Erreur côté serveur au renommage du titre.'); |
| 123 | } | 126 | } |
| 124 | }) | 127 | }) |
| 125 | .catch(error => { | 128 | .catch(error => { |
| @@ -168,7 +171,7 @@ function switchBlocsPositions(bloc_id, direction) { | |||
| 168 | } | 171 | } |
| 169 | else { | 172 | else { |
| 170 | 173 | ||
| 171 | console.error('Échec de l\'inversion'); | 174 | console.error("Échec de l'inversion côté serveur"); |
| 172 | } | 175 | } |
| 173 | }) | 176 | }) |
| 174 | .catch(error => { | 177 | .catch(error => { |
| @@ -187,17 +190,21 @@ function articlesOrderSelect(bloc_id){ | |||
| 187 | .then(response => response.json()) | 190 | .then(response => response.json()) |
| 188 | .then(data => { | 191 | .then(data => { |
| 189 | if(data.success){ | 192 | if(data.success){ |
| 190 | // inverser l'ordre des articles!! | 193 | // inversion des articles |
| 191 | const parent = document.getElementById(bloc_id).querySelector(".section_child"); | 194 | /*const parent = document.getElementById(bloc_id).querySelector(".section_child"); |
| 192 | const articles = Array.from(parent.querySelectorAll("article")); | 195 | const articles = Array.from(parent.querySelectorAll("article")); |
| 193 | articles.reverse().forEach(article => { | 196 | articles.reverse().forEach(article => { |
| 194 | parent.appendChild(article); // déplace dans le DOM, ne copie pas | 197 | parent.appendChild(article); // déplace dans le DOM, ne copie pas |
| 195 | }); | 198 | });*/ |
| 199 | |||
| 200 | // Ã cause de la pagination, au lieu d'inverser, on remplace les articles par les 1er dans le nouveau sens | ||
| 201 | document.getElementById(bloc_id).querySelector('.section_child').innerHTML = ''; | ||
| 202 | fetchArticles(bloc_id); | ||
| 196 | 203 | ||
| 197 | console.log('ordre ' + articles_order_select); | 204 | console.log('ordre ' + articles_order_select); |
| 198 | } | 205 | } |
| 199 | else{ | 206 | else{ |
| 200 | console.log("Erreur au changement de l'ordre d'affichage côté serveur"); | 207 | console.log("Erreur côté serveur au changement de l'ordre d'affichage"); |
| 201 | } | 208 | } |
| 202 | }) | 209 | }) |
| 203 | .catch(error => { | 210 | .catch(error => { |
| @@ -219,10 +226,10 @@ function changePresentation(bloc_id){ | |||
| 219 | document.getElementById(bloc_id).className = presentation; | 226 | document.getElementById(bloc_id).className = presentation; |
| 220 | document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = presentation === 'grid' ? 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))' : ''; | 227 | document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = presentation === 'grid' ? 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))' : ''; |
| 221 | document.getElementById('cols_min_width_edit_' + bloc_id).className = presentation === 'grid' ? '' : 'hidden'; | 228 | document.getElementById('cols_min_width_edit_' + bloc_id).className = presentation === 'grid' ? '' : 'hidden'; |
| 222 | console.log('changement de présentation'); | 229 | console.log('Changement de présentation'); |
| 223 | } | 230 | } |
| 224 | else{ | 231 | else{ |
| 225 | console.log('Erreur au changement de présentation côté serveur'); | 232 | console.log('Erreur côté serveur au changement de présentation'); |
| 226 | } | 233 | } |
| 227 | }) | 234 | }) |
| 228 | .catch(error => { | 235 | .catch(error => { |
| @@ -230,6 +237,7 @@ function changePresentation(bloc_id){ | |||
| 230 | }); | 237 | }); |
| 231 | } | 238 | } |
| 232 | 239 | ||
| 240 | // ressemble à changePaginationLimit | ||
| 233 | function changeColsMinWidth(bloc_id){ | 241 | function changeColsMinWidth(bloc_id){ |
| 234 | const cols_min_width_input = document.getElementById('cols_min_width_select_' + bloc_id); | 242 | const cols_min_width_input = document.getElementById('cols_min_width_select_' + bloc_id); |
| 235 | 243 | ||
| @@ -250,10 +258,58 @@ function changeColsMinWidth(bloc_id){ | |||
| 250 | if(data.success){ | 258 | if(data.success){ |
| 251 | document.getElementById(bloc_id).className = 'grid'; | 259 | document.getElementById(bloc_id).className = 'grid'; |
| 252 | document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))'; | 260 | document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))'; |
| 253 | console.log('changement de la largeur minimum en mode grille'); | 261 | console.log('Changement de la largeur minimum en mode grille'); |
| 262 | } | ||
| 263 | else{ | ||
| 264 | console.log('Erreur côté serveur au changement du nb de colonnes en mode grille'); | ||
| 265 | } | ||
| 266 | }) | ||
| 267 | .catch(error => { | ||
| 268 | console.error('Erreur:', error); | ||
| 269 | }); | ||
| 270 | } | ||
| 271 | |||
| 272 | // ressemble à changeColsMinWidth | ||
| 273 | function changePaginationLimit(bloc_id){ | ||
| 274 | const pagination_limit_input = document.getElementById('pagination_limit_' + bloc_id); | ||
| 275 | |||
| 276 | if(pagination_limit_input.value > 30){ | ||
| 277 | pagination_limit_input.value = 30; | ||
| 278 | } | ||
| 279 | else if(pagination_limit_input.value < 0){ | ||
| 280 | pagination_limit_input.value = 0; // fait joli dans la BDD, les valeurs négatives ont le même effet que 0 | ||
| 281 | } | ||
| 282 | |||
| 283 | fetch('index.php?bloc_edit=change_pagination_limit', { | ||
| 284 | method: 'POST', | ||
| 285 | headers: { 'Content-Type': 'application/json' }, | ||
| 286 | body: JSON.stringify({ id: bloc_id, pagination_limit: pagination_limit_input.value }) | ||
| 287 | }) | ||
| 288 | .then(response => response.json()) | ||
| 289 | .then(data => { | ||
| 290 | if(data.success){ | ||
| 291 | const parent = document.getElementById(bloc_id).querySelector('.section_child'); | ||
| 292 | const articles_list = parent.querySelectorAll('article'); | ||
| 293 | |||
| 294 | if(data.new_limit > data.old_limit || data.new_limit <= 0){ // si 0, fetchArticles va TOUT chercher! | ||
| 295 | parent.innerHTML = ''; // pas opti, mais améliorer ça serait très compliqué | ||
| 296 | fetchArticles(bloc_id); | ||
| 297 | } | ||
| 298 | else if(data.new_limit < articles_list.length){ | ||
| 299 | // retirer les articles | ||
| 300 | const articles_array = Array.from(articles_list).slice(0, data.new_limit); | ||
| 301 | parent.innerHTML = ''; | ||
| 302 | for(let i = 0; i < articles_array.length; i++){ | ||
| 303 | parent.appendChild(articles_array[i]); | ||
| 304 | } | ||
| 305 | // remettre le bouton "Articles suivants" | ||
| 306 | document.getElementById(bloc_id).querySelector('.fetch_articles').querySelector('button').className = ''; | ||
| 307 | } | ||
| 308 | |||
| 309 | console.log("Changement du nombre d'articles affichés simultanément dans ce bloc"); | ||
| 254 | } | 310 | } |
| 255 | else{ | 311 | else{ |
| 256 | console.log('Erreur au changement du nb de colonnes en mode grille côté serveur'); | 312 | console.log("Erreur côté serveur au changement du nb d'éléments affichés par la pagination"); |
| 257 | } | 313 | } |
| 258 | }) | 314 | }) |
| 259 | .catch(error => { | 315 | .catch(error => { |
diff --git a/public/js/tinymce.js b/public/js/tinymce.js index 97ecad8..d2f9c46 100644 --- a/public/js/tinymce.js +++ b/public/js/tinymce.js | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // code à réorganiser | 1 | // code à réorganiser |
| 2 | // seule certaines fonctions ont leur place dans Editor, d'autres servent à manipuler les articles d'une autre manière (déplacer, supprimer...) | 2 | // seules certaines fonctions ont leur place dans Editor, d'autres servent à manipuler les articles d'une autre manière (déplacer, supprimer...) |
| 3 | // => encapsuler Editor dans une classe Article (comme la balise) qui existe même quand l'éditeur est fermé | 3 | // => encapsuler Editor dans une classe Article (comme la balise) qui existe même quand l'éditeur est fermé |
| 4 | 4 | ||
| 5 | 5 | ||
| @@ -292,7 +292,7 @@ class Editor | |||
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | submit(clone = null){ | 294 | submit(clone = null){ |
| 295 | var content; | 295 | let content; |
| 296 | const params = new URL(document.location).searchParams; // "search" = ? et paramètres, searchParams = objet avec des getters | 296 | const params = new URL(document.location).searchParams; // "search" = ? et paramètres, searchParams = objet avec des getters |
| 297 | // Ã comparer avec: new URLSearchParams(window.location.search); | 297 | // Ã comparer avec: new URLSearchParams(window.location.search); |
| 298 | // c'est pareil ou pas? | 298 | // c'est pareil ou pas? |
| @@ -302,7 +302,7 @@ class Editor | |||
| 302 | const prefixes = ['t', 'p', 'i', 'd']; | 302 | const prefixes = ['t', 'p', 'i', 'd']; |
| 303 | const allElemsWithId = document.querySelectorAll('.data'); | 303 | const allElemsWithId = document.querySelectorAll('.data'); |
| 304 | content = {}; | 304 | content = {}; |
| 305 | var id_from_builder; | 305 | let id_from_builder; |
| 306 | 306 | ||
| 307 | allElemsWithId.forEach(element => { | 307 | allElemsWithId.forEach(element => { |
| 308 | const first_letter = element.id.charAt(0).toLowerCase(); | 308 | const first_letter = element.id.charAt(0).toLowerCase(); |
| @@ -394,14 +394,14 @@ class Editor | |||
| 394 | // restera ici jusqu'Ã ce que la gestion des balises soient faite ailleurs | 394 | // restera ici jusqu'Ã ce que la gestion des balises soient faite ailleurs |
| 395 | function makeNewArticleButtons(id, article_id, clone, placement = 'last') | 395 | function makeNewArticleButtons(id, article_id, clone, placement = 'last') |
| 396 | { | 396 | { |
| 397 | var share_btn = document.querySelector(`.share.hidden`); // combinaison de deux classes | 397 | let share_btn = document.querySelector(`.share.hidden`); // combinaison de deux classes |
| 398 | var new_btn = document.getElementById(`new-${id}`); | 398 | let new_btn = document.getElementById(`new-${id}`); |
| 399 | var edit_btn = document.getElementById(`edit-${id}`); | 399 | let edit_btn = document.getElementById(`edit-${id}`); |
| 400 | var pos_up_btn = document.getElementById(`position_up-${id}`); | 400 | let pos_up_btn = document.getElementById(`position_up-${id}`); |
| 401 | var pos_down_btn = document.getElementById(`position_down-${id}`); | 401 | let pos_down_btn = document.getElementById(`position_down-${id}`); |
| 402 | var delete_btn = document.getElementById(`delete-${id}`); | 402 | let delete_btn = document.getElementById(`delete-${id}`); |
| 403 | var cancel_btn = document.getElementById(`cancel-${id}`); | 403 | let cancel_btn = document.getElementById(`cancel-${id}`); |
| 404 | var submit_btn = document.getElementById(`submit-${id}`); | 404 | let submit_btn = document.getElementById(`submit-${id}`); |
| 405 | 405 | ||
| 406 | share_btn.classList.remove('hidden'); | 406 | share_btn.classList.remove('hidden'); |
| 407 | new_btn.classList.add('hidden'); | 407 | new_btn.classList.add('hidden'); |
| @@ -412,8 +412,8 @@ function makeNewArticleButtons(id, article_id, clone, placement = 'last') | |||
| 412 | //cancel_btn.classList.add('hidden'); | 412 | //cancel_btn.classList.add('hidden'); |
| 413 | //submit_btn.classList.add('hidden'); | 413 | //submit_btn.classList.add('hidden'); |
| 414 | 414 | ||
| 415 | var article = document.getElementById(id); | 415 | let article = document.getElementById(id); |
| 416 | var article_elem_parent = findParentByTagName(article, 'article'); | 416 | let article_elem_parent = findParentByTagName(article, 'article'); |
| 417 | 417 | ||
| 418 | share_btn.setAttribute('onclick', "copyInClipBoard('" + window.location.href + article_id + "')"); // # de l'ancre ajouté au clic sur le lien ouvrant l'éditeur | 418 | share_btn.setAttribute('onclick', "copyInClipBoard('" + window.location.href + article_id + "')"); // # de l'ancre ajouté au clic sur le lien ouvrant l'éditeur |
| 419 | article.id = article_id; | 419 | article.id = article_id; |
| @@ -430,7 +430,7 @@ function makeNewArticleButtons(id, article_id, clone, placement = 'last') | |||
| 430 | submit_btn.id = 'submit-' + article_id; | 430 | submit_btn.id = 'submit-' + article_id; |
| 431 | submit_btn.querySelector('button').setAttribute('onclick', "submitArticle('" + article_id + "')"); | 431 | submit_btn.querySelector('button').setAttribute('onclick', "submitArticle('" + article_id + "')"); |
| 432 | 432 | ||
| 433 | var section_child = article_elem_parent.parentNode.querySelector('.section_child'); // renommer section_child | 433 | let section_child = article_elem_parent.parentNode.querySelector('.section_child'); // renommer section_child |
| 434 | 434 | ||
| 435 | // parentNode vise la balise section | 435 | // parentNode vise la balise section |
| 436 | article_elem_parent.parentNode.replaceChild(clone.cloneNode(true), article_elem_parent); // clone du squelette pour le garder intact | 436 | article_elem_parent.parentNode.replaceChild(clone.cloneNode(true), article_elem_parent); // clone du squelette pour le garder intact |
diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php index 411c1dc..8bbef19 100644 --- a/src/controller/ArticleController.php +++ b/src/controller/ArticleController.php | |||
| @@ -6,10 +6,51 @@ declare(strict_types=1); | |||
| 6 | use App\Entity\Node; | 6 | use App\Entity\Node; |
| 7 | use App\Entity\Article; | 7 | use App\Entity\Article; |
| 8 | use Doctrine\ORM\EntityManager; | 8 | use Doctrine\ORM\EntityManager; |
| 9 | use Symfony\Component\HttpFoundation\Request; | ||
| 9 | use Symfony\Component\HttpFoundation\Response; | 10 | use Symfony\Component\HttpFoundation\Response; |
| 10 | 11 | ||
| 11 | class ArticleController | 12 | class ArticleController |
| 12 | { | 13 | { |
| 14 | static public function fetch(EntityManager $entityManager, Request $request): void | ||
| 15 | { | ||
| 16 | if($request->query->has('id') && !empty($request->query->get('id')) && $request->query->has('last_article')){ | ||
| 17 | //var_dump($request->query->get('last_article')); | ||
| 18 | $id = (int)$request->get('id'); // type et nettoie | ||
| 19 | $director = new Director($entityManager); | ||
| 20 | $director->findNodeById($id); | ||
| 21 | $parent_block = $director->getNode(); | ||
| 22 | |||
| 23 | if(Blocks::hasPresentation($parent_block->getName())){ | ||
| 24 | $get_articles_return = $director->getNextArticles($parent_block, $request); | ||
| 25 | $bulk_data = $get_articles_return[0]; | ||
| 26 | |||
| 27 | if($parent_block->getName() === 'post_block'){ | ||
| 28 | $builder_name = 'PostBuilder'; | ||
| 29 | } | ||
| 30 | elseif($parent_block->getName() === 'news_block'){ | ||
| 31 | $builder_name = 'NewBuilder'; | ||
| 32 | } | ||
| 33 | |||
| 34 | $html = ''; | ||
| 35 | foreach($bulk_data as $article){ | ||
| 36 | $builder = new $builder_name($article); | ||
| 37 | $html .= $builder->render(); | ||
| 38 | } | ||
| 39 | |||
| 40 | echo json_encode(['success' => true, 'html' => $html, 'truncated' => $get_articles_return[1]]); | ||
| 41 | die; | ||
| 42 | } | ||
| 43 | else{ | ||
| 44 | echo json_encode(['success' => false, 'error' => 'mauvais type de bloc']); | ||
| 45 | die; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | else{ | ||
| 49 | echo json_encode(['success' => false, 'error' => 'la requête ne comporte pas les paramètres attendus']); | ||
| 50 | die; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 13 | static public function editorSubmit(EntityManager $entityManager, array $json): void | 54 | static public function editorSubmit(EntityManager $entityManager, array $json): void |
| 14 | { | 55 | { |
| 15 | if(json_last_error() === JSON_ERROR_NONE) | 56 | if(json_last_error() === JSON_ERROR_NONE) |
diff --git a/src/controller/Director.php b/src/controller/Director.php index 8f038fa..9c1c6e3 100644 --- a/src/controller/Director.php +++ b/src/controller/Director.php | |||
| @@ -1,12 +1,14 @@ | |||
| 1 | <?php | 1 | <?php |
| 2 | // src/controller/Director.php | 2 | // src/controller/Director.php |
| 3 | 3 | ||
| 4 | // => src/model/Model.php serait mieux | ||
| 5 | |||
| 4 | declare(strict_types=1); | 6 | declare(strict_types=1); |
| 5 | 7 | ||
| 6 | use Doctrine\ORM\EntityManager; | 8 | use Doctrine\ORM\EntityManager; |
| 7 | use App\Entity\Page; | 9 | use App\Entity\Page; |
| 8 | use App\Entity\Node; | 10 | use App\Entity\Node; |
| 9 | //use Doctrine\ORM\QueryBuilder; | 11 | use Doctrine\ORM\QueryBuilder; |
| 10 | use Symfony\Component\HttpFoundation\Request; | 12 | use Symfony\Component\HttpFoundation\Request; |
| 11 | 13 | ||
| 12 | class Director | 14 | class Director |
| @@ -24,7 +26,9 @@ class Director | |||
| 24 | $this->node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants | 26 | $this->node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | public function makeMenuAndPaths(): void | 29 | // à déplacer dans Path ou un truc comme ça? |
| 30 | // couper Director en deux classes NodeModel et PageModel? | ||
| 31 | public function makeMenuAndPaths(): void // lit la table "page" | ||
| 28 | { | 32 | { |
| 29 | self::$menu_data = new Menu($this->entityManager); | 33 | self::$menu_data = new Menu($this->entityManager); |
| 30 | self::$page_path = new Path(); | 34 | self::$page_path = new Path(); |
| @@ -41,13 +45,12 @@ class Director | |||
| 41 | } | 45 | } |
| 42 | 46 | ||
| 43 | // affichage d'une page ordinaire | 47 | // affichage d'une page ordinaire |
| 44 | public function getWholePageData(Request $request): void | 48 | public function getWholePageData(Request $request): void // lit la table "node" + jointures |
| 45 | { | 49 | { |
| 46 | $id = CURRENT_PAGE === 'article' ? htmlspecialchars($request->query->get('id')) : ''; | 50 | $id = CURRENT_PAGE === 'article' ? htmlspecialchars($request->query->get('id')) : ''; |
| 47 | 51 | ||
| 48 | if($id === '') // page "normale" | 52 | if($id === ''){ // page "normale" |
| 49 | { | 53 | // récupérer tous les noeuds sauf les articles |
| 50 | // tous les noeuds sauf les articles, tri par page | ||
| 51 | $dql = "SELECT n FROM App\Entity\Node n WHERE n.name_node != 'new' AND n.name_node != 'post' AND (n.page = :page OR n.page IS null)"; | 54 | $dql = "SELECT n FROM App\Entity\Node n WHERE n.name_node != 'new' AND n.name_node != 'post' AND (n.page = :page OR n.page IS null)"; |
| 52 | $bulk_data = $this->entityManager | 55 | $bulk_data = $this->entityManager |
| 53 | ->createQuery($dql) | 56 | ->createQuery($dql) |
| @@ -57,45 +60,11 @@ class Director | |||
| 57 | // groupes d'articles triés par bloc, permet de paginer par bloc | 60 | // groupes d'articles triés par bloc, permet de paginer par bloc |
| 58 | foreach($bulk_data as $parent_block){ | 61 | foreach($bulk_data as $parent_block){ |
| 59 | if(Blocks::hasPresentation($parent_block->getName())){ // = post_block ou news_block | 62 | if(Blocks::hasPresentation($parent_block->getName())){ // = post_block ou news_block |
| 60 | $qb = $this->entityManager->createQueryBuilder(); | 63 | $bulk_data = array_merge($bulk_data, $this->getNextArticles($parent_block, $request)[0]); |
| 61 | $qb->select('n') | ||
| 62 | ->from('App\Entity\Node', 'n') | ||
| 63 | ->where('n.parent = :parent') | ||
| 64 | ->setParameter('parent', $parent_block); | ||
| 65 | |||
| 66 | if($parent_block->getName() === 'post_block'){ | ||
| 67 | $qb->orderBy('n.position'); | ||
| 68 | } | ||
| 69 | elseif($parent_block->getName() === 'news_block'){ | ||
| 70 | $qb->join('n.article', 'a'); | ||
| 71 | if($parent_block->getNodeData()->getChronoOrder() ?? false){ // ordre antichrono par défaut | ||
| 72 | $qb->orderBy('a.date_time', 'ASC'); | ||
| 73 | } | ||
| 74 | else{ | ||
| 75 | $qb->orderBy('a.date_time', 'DESC'); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | // pagination | ||
| 80 | $limit = $parent_block->getNodeData()->getPaginationLimit() ?? 0; // 0 par défaut = pas de pagination, sinon 12 rend bien avec des grilles de 2, 3 ou 4 colonnes | ||
| 81 | if($limit > 0){ | ||
| 82 | //$this->paginateWithCursor($qb, $request->query->get('last_position') ?? 0, $limit); | ||
| 83 | $qb->andWhere('n.position > :last_position') | ||
| 84 | ->setParameter('last_position', $request->query->get('last_position') ?? 0) | ||
| 85 | ->setMaxResults($limit); | ||
| 86 | |||
| 87 | $nb_pages = $this->getNumberOfPages($parent_block, $limit); // nombres de "pages" d'articles | ||
| 88 | if($nb_pages > 1){ | ||
| 89 | //$parent_block->setNumberOfPages($nb_pages); // => navigation en HTML | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | $bulk_data = array_merge($bulk_data, $qb->getQuery()->getResult()); | ||
| 94 | } | 64 | } |
| 95 | } | 65 | } |
| 96 | } | 66 | } |
| 97 | else // page "article" | 67 | else{ // page "article" |
| 98 | { | ||
| 99 | $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page OR n.page IS null OR n.id_node = :id'; | 68 | $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page OR n.page IS null OR n.id_node = :id'; |
| 100 | $bulk_data = $this->entityManager | 69 | $bulk_data = $this->entityManager |
| 101 | ->createQuery($dql) | 70 | ->createQuery($dql) |
| @@ -103,18 +72,74 @@ class Director | |||
| 103 | ->setParameter('id', $id) | 72 | ->setParameter('id', $id) |
| 104 | ->getResult(); | 73 | ->getResult(); |
| 105 | } | 74 | } |
| 75 | |||
| 106 | $this->makeNodeTree($bulk_data); | 76 | $this->makeNodeTree($bulk_data); |
| 107 | } | 77 | } |
| 108 | 78 | ||
| 109 | /*private function paginateWithCursor(QueryBuilder $qb, int $last_position = 0, int $limit = 0): void | 79 | // récupération d'articles |
| 80 | public function getNextArticles(Node $parent_block, Request $request): array | ||
| 81 | { | ||
| 82 | $qb = $this->entityManager->createQueryBuilder(); | ||
| 83 | $qb->select('n') | ||
| 84 | ->from('App\Entity\Node', 'n') | ||
| 85 | ->where('n.parent = :parent') | ||
| 86 | ->setParameter('parent', $parent_block); | ||
| 87 | |||
| 88 | if($parent_block->getName() === 'post_block'){ | ||
| 89 | $qb->orderBy('n.position'); | ||
| 90 | } | ||
| 91 | elseif($parent_block->getName() === 'news_block'){ | ||
| 92 | $qb->join('n.article', 'a'); | ||
| 93 | if($parent_block->getNodeData()->getChronoOrder() ?? false){ // ordre antichrono par défaut | ||
| 94 | $qb->orderBy('a.date_time', 'ASC'); | ||
| 95 | } | ||
| 96 | else{ | ||
| 97 | $qb->orderBy('a.date_time', 'DESC'); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | // pagination | ||
| 102 | $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD | ||
| 103 | $this->paginateWithCursor($qb, $parent_block, $request->query->get('last_article')); | ||
| 104 | $result = $qb->getQuery()->getResult(); | ||
| 105 | |||
| 106 | // il reste des articles à récupérer SI on vient d'en récupérer trop | ||
| 107 | // ET on gère le cas particulier de $limit <= 0 | ||
| 108 | $truncated = false; | ||
| 109 | if(count($result) > $limit && $limit > 0){ // si nb résultat > limit > 0 | ||
| 110 | $truncated = true; | ||
| 111 | array_pop($result); // compenser le $limit + 1 dans paginateWithCursor | ||
| 112 | } | ||
| 113 | |||
| 114 | return [$result, $truncated]; // besoin exceptionnel de retourner deux valeurs | ||
| 115 | } | ||
| 116 | |||
| 117 | private function paginateWithCursor(QueryBuilder $qb, Node $parent_block, ?string $last_article): void | ||
| 110 | { | 118 | { |
| 111 | $qb->andWhere('n.position > :last_position') | 119 | //var_dump($last_article); |
| 112 | ->setParameter('last_position', $last_position) | 120 | $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD |
| 113 | ->setMaxResults($limit); | 121 | |
| 114 | }*/ | 122 | if($limit > 0){ // si 0 ou moins pas de pagination |
| 123 | // nombres de "pages" d'articles | ||
| 124 | $nb_pages = $this->getNumberOfPages($parent_block, $limit); | ||
| 125 | $parent_block->getNodeData()->setNumberOfPages($nb_pages > 1 ? $nb_pages : 1); | ||
| 126 | |||
| 127 | // adaptation de la requête | ||
| 128 | if($parent_block->getName() === 'post_block'){ | ||
| 129 | $qb->andWhere('n.position > :last_position') | ||
| 130 | ->setParameter('last_position', empty($last_article) ? 0 : $last_article) | ||
| 131 | ->setMaxResults($limit + 1); | ||
| 132 | } | ||
| 133 | elseif($parent_block->getName() === 'news_block'){ | ||
| 134 | $cursor_start = $parent_block->getNodeData()->getChronoOrder() ? '1970-01-01' : '9999-12-31'; | ||
| 135 | $qb->andWhere($parent_block->getNodeData()->getChronoOrder() ? 'a.date_time > :date_time' : 'a.date_time < :date_time') | ||
| 136 | ->setParameter('date_time', empty($last_article) ? $cursor_start : $last_article) | ||
| 137 | ->setMaxResults($limit + 1); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 115 | 141 | ||
| 116 | // requête à part n'alimentant pas $bulk_data | 142 | // le Paginator de doctrine le fait aussi si on décidait de s'en servir |
| 117 | // fonctionnalité offerte par le Paginator de doctrine si on décidait de s'en servir | ||
| 118 | private function getNumberOfPages(Node $parent_block, int $limit): int | 143 | private function getNumberOfPages(Node $parent_block, int $limit): int |
| 119 | { | 144 | { |
| 120 | $dql = 'SELECT COUNT(n.id_node) FROM App\Entity\Node n WHERE n.parent = :parent'; | 145 | $dql = 'SELECT COUNT(n.id_node) FROM App\Entity\Node n WHERE n.parent = :parent'; |
| @@ -129,11 +154,9 @@ class Director | |||
| 129 | { | 154 | { |
| 130 | // puis on les range | 155 | // puis on les range |
| 131 | // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD) | 156 | // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD) |
| 132 | foreach($bulk_data as $node) | 157 | foreach($bulk_data as $node){ |
| 133 | { | ||
| 134 | // premier niveau | 158 | // premier niveau |
| 135 | if($node->getParent() == null) | 159 | if($node->getParent() == null){ |
| 136 | { | ||
| 137 | $this->node->addChild($node); | 160 | $this->node->addChild($node); |
| 138 | 161 | ||
| 139 | // spécifique page article | 162 | // spécifique page article |
| @@ -142,8 +165,7 @@ class Director | |||
| 142 | } | 165 | } |
| 143 | } | 166 | } |
| 144 | // autres niveaux | 167 | // autres niveaux |
| 145 | else | 168 | else{ |
| 146 | { | ||
| 147 | $node->getParent()->addChild($node); | 169 | $node->getParent()->addChild($node); |
| 148 | 170 | ||
| 149 | // spécifique page article | 171 | // spécifique page article |
diff --git a/src/controller/PageManagementController.php b/src/controller/PageManagementController.php index 2cc88a5..8efcb79 100644 --- a/src/controller/PageManagementController.php +++ b/src/controller/PageManagementController.php | |||
| @@ -334,4 +334,21 @@ class PageManagementController | |||
| 334 | } | 334 | } |
| 335 | die; | 335 | die; |
| 336 | } | 336 | } |
| 337 | static public function changePaginationLimit(EntityManager $entityManager, array $json): void | ||
| 338 | { | ||
| 339 | if(isset($json['id']) && isset($json['pagination_limit'])){ | ||
| 340 | $director = new Director($entityManager); | ||
| 341 | $director->findNodeById($json['id']); | ||
| 342 | $old_limit = $director->getNode()->getNodeData()->getPaginationLimit() ?? 12; | ||
| 343 | $director->getNode()->getNodeData()->setPaginationLimit((int)$json['pagination_limit']); // attention conversion? | ||
| 344 | |||
| 345 | $entityManager->flush(); | ||
| 346 | |||
| 347 | echo json_encode(['success' => true, 'old_limit' => $old_limit, 'new_limit' => $json['pagination_limit']]); | ||
| 348 | } | ||
| 349 | else{ | ||
| 350 | echo json_encode(['success' => false]); | ||
| 351 | } | ||
| 352 | die; | ||
| 353 | } | ||
| 337 | } \ No newline at end of file | 354 | } \ No newline at end of file |
diff --git a/src/model/entities/NodeData.php b/src/model/entities/NodeData.php index 1d7db4c..d8281c0 100644 --- a/src/model/entities/NodeData.php +++ b/src/model/entities/NodeData.php | |||
| @@ -48,6 +48,8 @@ class NodeData | |||
| 48 | )] | 48 | )] |
| 49 | private Collection $images; | 49 | private Collection $images; |
| 50 | 50 | ||
| 51 | private int $nb_pages = 1; | ||
| 52 | |||
| 51 | public function __construct(array $data, Node $node, Collection $images = new ArrayCollection, ?string $presentation = null, ?bool $chrono_order = null) | 53 | public function __construct(array $data, Node $node, Collection $images = new ArrayCollection, ?string $presentation = null, ?bool $chrono_order = null) |
| 52 | { | 54 | { |
| 53 | $this->data = $data; | 55 | $this->data = $data; |
| @@ -111,7 +113,20 @@ class NodeData | |||
| 111 | 113 | ||
| 112 | public function getPaginationLimit(): ?int | 114 | public function getPaginationLimit(): ?int |
| 113 | { | 115 | { |
| 114 | return $this->pagination_limit ?? null; | 116 | $default = 12; // si 0 pas de pagination, 12 rend bien avec des grilles de 2, 3 ou 4 colonnes |
| 117 | return $this->pagination_limit === null ? $default : $this->pagination_limit; | ||
| 118 | } | ||
| 119 | public function setPaginationLimit(int $pagination_limit): void | ||
| 120 | { | ||
| 121 | $this->pagination_limit = $pagination_limit; | ||
| 122 | } | ||
| 123 | public function getNumberOfPages(): int | ||
| 124 | { | ||
| 125 | return $this->nb_pages; | ||
| 126 | } | ||
| 127 | public function setNumberOfPages(int $nb_pages): void | ||
| 128 | { | ||
| 129 | $this->nb_pages = $nb_pages; | ||
| 115 | } | 130 | } |
| 116 | 131 | ||
| 117 | /*public function setNode(Node $node): void | 132 | /*public function setNode(Node $node): void |
diff --git a/src/router.php b/src/router.php index 773a25c..8d19e49 100644 --- a/src/router.php +++ b/src/router.php | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?php | 1 | <?php |
| 2 | // src/router.php | 2 | // src/router.php |
| 3 | // | 3 | // |
| 4 | /* fonctionnement du routeur | 4 | /* fonctionnement: |
| 5 | => 1er test, méthode http: GET, POST ou autre chose | 5 | => 1er test, méthode http: GET, POST ou autre chose |
| 6 | => 2ème test, type de contenu (méthode POST uniquement): | 6 | => 2ème test, type de contenu (méthode POST uniquement): |
| 7 | "application/x-www-form-urlencoded" = formulaire | 7 | "application/x-www-form-urlencoded" = formulaire |
| @@ -13,22 +13,27 @@ $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' requête AJAX xhs, non uti | |||
| 13 | 13 | ||
| 14 | declare(strict_types=1); | 14 | declare(strict_types=1); |
| 15 | 15 | ||
| 16 | if($_SERVER['REQUEST_METHOD'] === 'GET'){ | 16 | if($request->getMethod() === 'GET'){ |
| 17 | // table "user" vide | 17 | // table "user" vide |
| 18 | if(!UserController::existUsers($entityManager)){ | 18 | if(!UserController::existUsers($entityManager)){ |
| 19 | require '../src/view/templates/user_create.php'; | 19 | require AbstractBuilder::VIEWS_PATH . 'user_create.php'; |
| 20 | die; | 20 | die; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | // bouton déconnexion | 23 | // bouton déconnexion (méthode GET parce que l'utilisateur ne modifie plus de données à partir de là ) |
| 24 | if($request->query->has('action') && $request->query->get('action') === 'deconnection'){ | 24 | if($request->query->has('action') && $request->query->get('action') === 'deconnection'){ |
| 25 | UserController::disconnect($entityManager); | 25 | UserController::disconnect($entityManager); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | // articles suivants | ||
| 29 | if($request->query->has('fetch') && $request->query->get('fetch') === 'next_articles'){ | ||
| 30 | ArticleController::fetch($entityManager, $request); | ||
| 31 | } | ||
| 32 | |||
| 28 | // données du calendrier | 33 | // données du calendrier |
| 29 | // création du calendrier et changement de dates affichées (boutons flèches mais pas changement de vue) | 34 | // création du calendrier et changement de dates affichées (boutons flèches mais pas changement de vue) |
| 30 | if($_SERVER['REQUEST_METHOD'] === 'GET' && $request->query->has('action') && $request->query->get('action') === 'get_events' | 35 | if($request->query->has('action') && $request->query->get('action') === 'get_events' |
| 31 | && $request->query->has('start') && $request->query->has('end') && empty($_POST)) | 36 | && $request->query->has('start') && $request->query->has('end') && empty($request->getPayload()->all())) // getPayload ne récupère pas que des POST |
| 32 | { | 37 | { |
| 33 | CalendarController::getData($entityManager); | 38 | CalendarController::getData($entityManager); |
| 34 | } | 39 | } |
| @@ -43,7 +48,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET'){ | |||
| 43 | } | 48 | } |
| 44 | 49 | ||
| 45 | 50 | ||
| 46 | elseif($_SERVER['REQUEST_METHOD'] === 'POST'){ | 51 | elseif($request->getMethod() === 'POST'){ |
| 47 | /* -- contrôleurs appellables par tout le monde -- */ | 52 | /* -- contrôleurs appellables par tout le monde -- */ |
| 48 | 53 | ||
| 49 | // table "user" vide | 54 | // table "user" vide |
| @@ -54,8 +59,7 @@ elseif($_SERVER['REQUEST_METHOD'] === 'POST'){ | |||
| 54 | // requêtes JSON avec fetch() | 59 | // requêtes JSON avec fetch() |
| 55 | if($_SERVER['CONTENT_TYPE'] === 'application/json') | 60 | if($_SERVER['CONTENT_TYPE'] === 'application/json') |
| 56 | { | 61 | { |
| 57 | $data = file_get_contents('php://input'); | 62 | $json = json_decode($request->getContent(), true); // = json_decode(file_get_contents('php://input'), true); |
| 58 | $json = json_decode($data, true); | ||
| 59 | 63 | ||
| 60 | if(isset($_GET['action'])) | 64 | if(isset($_GET['action'])) |
| 61 | { | 65 | { |
| @@ -195,6 +199,9 @@ elseif($_SERVER['REQUEST_METHOD'] === 'POST'){ | |||
| 195 | elseif($request->query->get('bloc_edit') === 'change_cols_min_width'){ | 199 | elseif($request->query->get('bloc_edit') === 'change_cols_min_width'){ |
| 196 | PageManagementController::changeColsMinWidth($entityManager, $json); | 200 | PageManagementController::changeColsMinWidth($entityManager, $json); |
| 197 | } | 201 | } |
| 202 | elseif($request->query->get('bloc_edit') === 'change_pagination_limit'){ | ||
| 203 | PageManagementController::changePaginationLimit($entityManager, $json); | ||
| 204 | } | ||
| 198 | } | 205 | } |
| 199 | } | 206 | } |
| 200 | 207 | ||
| @@ -316,7 +323,7 @@ if(isset($response)){ | |||
| 316 | header('Location: ' . new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil'])); | 323 | header('Location: ' . new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil'])); |
| 317 | } | 324 | } |
| 318 | // redirection après traitement de formulaires HTTP | 325 | // redirection après traitement de formulaires HTTP |
| 319 | elseif($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ | 326 | elseif($request->getMethod() === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ |
| 320 | $response_data = json_decode(($response)->getContent(), true); | 327 | $response_data = json_decode(($response)->getContent(), true); |
| 321 | $url = new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil']); | 328 | $url = new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil']); |
| 322 | $url->addParams(['success' => $response_data['success'], 'message' => $response_data['message']]); | 329 | $url->addParams(['success' => $response_data['success'], 'message' => $response_data['message']]); |
| @@ -329,7 +336,7 @@ if(isset($response)){ | |||
| 329 | } | 336 | } |
| 330 | // pas utilisation de RESPONSE (cas destiné à disparaître) | 337 | // pas utilisation de RESPONSE (cas destiné à disparaître) |
| 331 | else{ | 338 | else{ |
| 332 | if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ | 339 | if($request->getMethod() === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ |
| 333 | header("Location: " . new URL(['error' => 'erreur côté serveur'])); | 340 | header("Location: " . new URL(['error' => 'erreur côté serveur'])); |
| 334 | } | 341 | } |
| 335 | else{ | 342 | else{ |
| @@ -337,4 +344,4 @@ else{ | |||
| 337 | echo "erreur côté serveur"; | 344 | echo "erreur côté serveur"; |
| 338 | } | 345 | } |
| 339 | } | 346 | } |
| 340 | //die; // inutile normalement \ No newline at end of file | 347 | //die; // inutile \ No newline at end of file |
diff --git a/src/view/AbstractBuilder.php b/src/view/AbstractBuilder.php index ab5e389..0748df0 100644 --- a/src/view/AbstractBuilder.php +++ b/src/view/AbstractBuilder.php | |||
| @@ -7,7 +7,7 @@ use App\Entity\Node; | |||
| 7 | 7 | ||
| 8 | abstract class AbstractBuilder | 8 | abstract class AbstractBuilder |
| 9 | { | 9 | { |
| 10 | protected const string VIEWS_PATH = '../src/view/templates/'; | 10 | public const string VIEWS_PATH = '../src/view/templates/'; |
| 11 | protected string $html = ''; | 11 | protected string $html = ''; |
| 12 | protected int $id_node; | 12 | protected int $id_node; |
| 13 | 13 | ||
| @@ -44,7 +44,7 @@ abstract class AbstractBuilder | |||
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | protected function snakeToPascalCase(string $input): string | 47 | private function snakeToPascalCase(string $input): string |
| 48 | { | 48 | { |
| 49 | return str_replace('_', '', ucwords($input, '_')); | 49 | return str_replace('_', '', ucwords($input, '_')); |
| 50 | } | 50 | } |
diff --git a/src/view/NewBuilder.php b/src/view/NewBuilder.php index 83dd728..ec48541 100644 --- a/src/view/NewBuilder.php +++ b/src/view/NewBuilder.php | |||
| @@ -51,9 +51,7 @@ class NewBuilder extends AbstractBuilder | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | $content = ''; | 53 | $content = ''; |
| 54 | 54 | if(CURRENT_PAGE === 'article'){ | |
| 55 | // page article unique | ||
| 56 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ | ||
| 57 | $content = $node->getArticle()->getContent(); | 55 | $content = $node->getArticle()->getContent(); |
| 58 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []) . '"><button>Retour</button></a></p>'; | 56 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []) . '"><button>Retour</button></a></p>'; |
| 59 | $overflow = ''; | 57 | $overflow = ''; |
| @@ -84,7 +82,7 @@ class NewBuilder extends AbstractBuilder | |||
| 84 | $date_buttons = ''; | 82 | $date_buttons = ''; |
| 85 | $admin_buttons = ''; | 83 | $admin_buttons = ''; |
| 86 | if($_SESSION['admin']){ | 84 | if($_SESSION['admin']){ |
| 87 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ | 85 | if(CURRENT_PAGE === 'article'){ |
| 88 | $title_js = 'onclick="openEditor(\'' . $id_title . '\')"'; | 86 | $title_js = 'onclick="openEditor(\'' . $id_title . '\')"'; |
| 89 | $modify_title = '<p id="edit-' . $id_title . '"><button ' . $title_js . '><img class="action_icon" src="assets/edit.svg">Titre</button></p>' . "\n"; | 87 | $modify_title = '<p id="edit-' . $id_title . '"><button ' . $title_js . '><img class="action_icon" src="assets/edit.svg">Titre</button></p>' . "\n"; |
| 90 | $close_js_title = 'onclick="closeEditor(\'' . $id_title . '\')"'; | 88 | $close_js_title = 'onclick="closeEditor(\'' . $id_title . '\')"'; |
diff --git a/src/view/NewsBlockBuilder.php b/src/view/NewsBlockBuilder.php index 963afe6..4c7c4ec 100644 --- a/src/view/NewsBlockBuilder.php +++ b/src/view/NewsBlockBuilder.php | |||
| @@ -28,6 +28,7 @@ class NewsBlockBuilder extends AbstractBuilder | |||
| 28 | $min_width = $node->getNodeData()->getColsMinWidth(); | 28 | $min_width = $node->getNodeData()->getColsMinWidth(); |
| 29 | $cols_min_width = 'grid-template-columns: repeat(auto-fit, minmax(' . (string)$min_width . 'px, 1fr));'; | 29 | $cols_min_width = 'grid-template-columns: repeat(auto-fit, minmax(' . (string)$min_width . 'px, 1fr));'; |
| 30 | } | 30 | } |
| 31 | $fetch_button_hidden = $node->getNodeData()->getNumberOfPages() > 1 ? '' : ' hidden'; | ||
| 31 | 32 | ||
| 32 | // ajouter un article | 33 | // ajouter un article |
| 33 | $new_article = ''; | 34 | $new_article = ''; |
| @@ -54,7 +55,7 @@ class NewsBlockBuilder extends AbstractBuilder | |||
| 54 | $html = ''; | 55 | $html = ''; |
| 55 | $admin_buttons = $new_button . $modify_article . $delete_article . $close_editor . $submit_article; | 56 | $admin_buttons = $new_button . $modify_article . $delete_article . $close_editor . $submit_article; |
| 56 | 57 | ||
| 57 | // post vide mis là pour le bouton "Nouvel article" => déplace vers page "article" | 58 | // insérer post.php pour le bouton "Nouvel article", new.php pour les vrais articles |
| 58 | ob_start(); | 59 | ob_start(); |
| 59 | require self::VIEWS_PATH . 'post.php'; // nécéssite $admin_buttons et $html | 60 | require self::VIEWS_PATH . 'post.php'; // nécéssite $admin_buttons et $html |
| 60 | $new_article = ob_get_clean(); | 61 | $new_article = ob_get_clean(); |
diff --git a/src/view/PostBlockBuilder.php b/src/view/PostBlockBuilder.php index ba54901..ba4de12 100644 --- a/src/view/PostBlockBuilder.php +++ b/src/view/PostBlockBuilder.php | |||
| @@ -28,6 +28,7 @@ class PostBlockBuilder extends AbstractBuilder | |||
| 28 | $min_width = $node->getNodeData()->getColsMinWidth(); | 28 | $min_width = $node->getNodeData()->getColsMinWidth(); |
| 29 | $cols_min_width = 'grid-template-columns: repeat(auto-fit, minmax(' . (string)$min_width . 'px, 1fr));'; | 29 | $cols_min_width = 'grid-template-columns: repeat(auto-fit, minmax(' . (string)$min_width . 'px, 1fr));'; |
| 30 | } | 30 | } |
| 31 | $fetch_button_hidden = $node->getNodeData()->getNumberOfPages() > 1 ? '' : ' hidden'; | ||
| 31 | 32 | ||
| 32 | // ajouter un article | 33 | // ajouter un article |
| 33 | // => fait un peu double emploi avec PostBuilder | 34 | // => fait un peu double emploi avec PostBuilder |
diff --git a/src/view/templates/modify_block.php b/src/view/templates/modify_block.php index 1d097e0..3620100 100644 --- a/src/view/templates/modify_block.php +++ b/src/view/templates/modify_block.php | |||
| @@ -47,4 +47,11 @@ if(Blocks::hasPresentation($child_node->getName())){ | |||
| 47 | <?php | 47 | <?php |
| 48 | } | 48 | } |
| 49 | ?> | 49 | ?> |
| 50 | <div class="pagination_limit"> | ||
| 51 | <label for="pagination_limit_<?= $child_node->getId() ?>"> | ||
| 52 | Nombre max d'articles affichés | ||
| 53 | <input type="number" id="pagination_limit_<?= $child_node->getId() ?>" name="pagination_limit" onchange="changePaginationLimit(<?= $child_node->getId() ?>)" min="0" max="30" value="<?= $child_node->getNodeData()->getPaginationLimit() ?>"> | ||
| 54 | <i>(mettre 0 désactive la pagination)</i> | ||
| 55 | </label> | ||
| 56 | </div> | ||
| 50 | </div> \ No newline at end of file | 57 | </div> \ No newline at end of file |
diff --git a/src/view/templates/news_block.php b/src/view/templates/news_block.php index 9d01513..43dbe01 100644 --- a/src/view/templates/news_block.php +++ b/src/view/templates/news_block.php | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | <?php declare(strict_types=1); ?> | 1 | <?php declare(strict_types=1); ?> |
| 2 | <section class="<?= $section_class ?>" id="<?= $this->id_node ?>"> | 2 | <section class="<?= $section_class ?>" block-type="<?= $node->getName() ?>" id="<?= $this->id_node ?>"> |
| 3 | <h3><?= $title ?></h3> | 3 | <h3><?= $title ?></h3> |
| 4 | <?= $new_article ?> | 4 | <?= $new_article ?> |
| 5 | <script> | 5 | <script> |
| @@ -8,4 +8,7 @@ | |||
| 8 | <div class="section_child" style="<?= $cols_min_width ?>"> | 8 | <div class="section_child" style="<?= $cols_min_width ?>"> |
| 9 | <?= $content ?> | 9 | <?= $content ?> |
| 10 | </div> | 10 | </div> |
| 11 | <div class="fetch_articles"> | ||
| 12 | <button class="<?= $fetch_button_hidden ?>" onclick="fetchArticles(<?= $this->id_node ?>)">Articles suivants</button> | ||
| 13 | </div> | ||
| 11 | </section> \ No newline at end of file | 14 | </section> \ No newline at end of file |
diff --git a/src/view/templates/post_block.php b/src/view/templates/post_block.php index 9d01513..43dbe01 100644 --- a/src/view/templates/post_block.php +++ b/src/view/templates/post_block.php | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | <?php declare(strict_types=1); ?> | 1 | <?php declare(strict_types=1); ?> |
| 2 | <section class="<?= $section_class ?>" id="<?= $this->id_node ?>"> | 2 | <section class="<?= $section_class ?>" block-type="<?= $node->getName() ?>" id="<?= $this->id_node ?>"> |
| 3 | <h3><?= $title ?></h3> | 3 | <h3><?= $title ?></h3> |
| 4 | <?= $new_article ?> | 4 | <?= $new_article ?> |
| 5 | <script> | 5 | <script> |
| @@ -8,4 +8,7 @@ | |||
| 8 | <div class="section_child" style="<?= $cols_min_width ?>"> | 8 | <div class="section_child" style="<?= $cols_min_width ?>"> |
| 9 | <?= $content ?> | 9 | <?= $content ?> |
| 10 | </div> | 10 | </div> |
| 11 | <div class="fetch_articles"> | ||
| 12 | <button class="<?= $fetch_button_hidden ?>" onclick="fetchArticles(<?= $this->id_node ?>)">Articles suivants</button> | ||
| 13 | </div> | ||
| 11 | </section> \ No newline at end of file | 14 | </section> \ No newline at end of file |
