From 4efa19d4357ab204d62397f1849e4651906e0e70 Mon Sep 17 00:00:00 2001 From: polo Date: Sat, 10 May 2025 23:51:37 +0200 Subject: =?UTF-8?q?fichiers=20manquant=20du=20commit=20pr=C3=A9c=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/main.css | 215 ------------ public/css/menu.css | 4 +- public/js/main.js | 81 +---- src/controller/ajax.php | 744 +++++++++++++++++++++------------------- src/controller/installation.php | 39 ++- src/controller/post.php | 30 +- src/model/entities/NodeData.php | 10 +- src/model/entities/Page.php | 8 + src/view/BreadcrumbBuilder.php | 4 +- src/view/GridBuilder.php | 4 +- src/view/HeadBuilder.php | 8 +- src/view/MainBuilder.php | 47 ++- src/view/NavBuilder.php | 4 +- src/view/ViewBuilder.php | 2 + 14 files changed, 499 insertions(+), 701 deletions(-) delete mode 100644 public/css/main.css diff --git a/public/css/main.css b/public/css/main.css deleted file mode 100644 index 870082a..0000000 --- a/public/css/main.css +++ /dev/null @@ -1,215 +0,0 @@ -main -{ - margin: auto; - /*max-width: 1200px;*/ - background-color: #E3F3FF; - padding: 15px 0; -} -section > h3 -{ - padding: 15px; - margin: 0; - text-align: center; -} -.grid_columns -{ - display: grid; - grid-template-columns: repeat(3, 1fr); -} -@media screen and (max-width: 800px) -{ - .grid_columns - { - grid-template-columns: repeat(2, 1fr); - } -} -@media screen and (max-width: 550px) -{ - .grid_columns - { - display: block; - } -} -.galery_photos -{ - display: flex; - flex-wrap: wrap; - justify-content: space-evenly; -} -.galery_photos .html_from_editor img -{ - max-width: 300px; - max-height: 200px; -} -article -{ - /*display: flex;*/ - background-color: white; - margin: 15px; - padding: 0 15px; - /*min-height: 150px;*/ -} -article .logo2 -{ - vertical-align: middle; - max-width: 200px; - max-height: 200px; - margin-right: 15px; -} -.new_content, .article_content -{ - width: 100%; -} -.new_content -{ - /*max-height: 400;*/ - overflow: hidden; -} -article img -{ - width: 100%; - height: auto; -} - -.action_icon -{ - width: 24px; - vertical-align: bottom; - border: white 2px solid; /* invisible */ -} -button .action_icon -{ - border: none; -} -.action_icon:hover -{ - background-color: #ffff00; - border-radius: 4px; - border: lightgrey 2px outset; - cursor: pointer; -} -button .action_icon:hover -{ - border: none; -} - -.button_zone -{ - display: flex; -} - -.share -{ - float: right; -} -.article_title_zone -{ - padding: 10px; -} -.under_an_article -{ - display: flex; - justify-content: space-between; - font-size: small; -} -.under_an_article img -{ - width: 24px; - margin-right: 5px; - vertical-align: middle; -} -.article_admin_zone -{ - display: flex; - justify-content: end; -} -main button -{ - color: #ff1d04; - font-size: medium; - border-radius: 4px; - background-color: white; - border: lightgrey 2px outset; /* rend identiques les boutons firefox et chromium */ -} -main button:hover -{ - background-color: #ffff00; - border-radius: 4px; - cursor: pointer; -} - -article a:hover -{ - cursor: pointer; -} - - - -/* -- mode modification d'une page -- */ -/*.modif_page_explanations -{ - background-color: white; - padding: 10px; - margin: 10px 20px; -} -.modif_page_explanations div -{ - display: flex; - flex-wrap: wrap; - font-size: smaller; -}*/ -.edit_bloc_zone -{ - background-color: white; - padding: 10px; - margin: 10px 15px; - display: flex; - justify-content: space-evenly; - flex-wrap: wrap; -} -.edit_bloc_zone p -{ - margin: 5px; -} -.new_bloc, .modify_bloc -{ - /*background-color: white; - padding: 10px; - margin: 10px 20px;*/ -} -.new_bloc p -{ - /*margin: 5px;*/ -} -.new_bloc #bloc_title -{ - width: 70%; - max-width: 300px; -} -.new_bloc form select, .new_bloc form input[type=submit], .modify_bloc form input[type=submit] -{ - color: #ff1d04; - font-size: medium; - border-radius: 4px; - background-color: white; - border: lightgrey 2px outset; -} -select:hover -{ - cursor: pointer; -} -.new_bloc form input[type=submit]:hover, .modify_bloc form input[type=submit]:hover -{ - background-color: #ffff00; - border-radius: 4px; - cursor: pointer; -} -.modify_bloc > div -{ - display: flex; - align-items: baseline; -} -.modify_bloc img -{ - vertical-align: middle; -} \ No newline at end of file diff --git a/public/css/menu.css b/public/css/menu.css index 61e8a01..68e2b2a 100644 --- a/public/css/menu.css +++ b/public/css/menu.css @@ -1,4 +1,4 @@ -/* page "Menu et chemins" uniquement */ +/*-- page "Menu et chemins" uniquement --*/ .menu { @@ -68,7 +68,7 @@ { width: 20px; vertical-align: middle; - border: 2px #e3f3ff solid; + border: 2px transparent solid; } .menu #location:hover, .menu input[type=submit]:hover, .move_entry_icon:hover { diff --git a/public/js/main.js b/public/js/main.js index 7dacb7a..071a1db 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -36,6 +36,7 @@ function toastNotify(message) { setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 3000); } + // complète les fonctions dans tinymce.js function switchPositions(article_id, direction) { @@ -202,84 +203,4 @@ function findParent(element, tag_name){ element = element.parentElement; } return null; -} - - -/* -- mode Modification d'une page -- */ -function renamePageBloc(bloc_id){ - const input = document.getElementById("bloc_rename_" + bloc_id); - const title = document.getElementById(bloc_id).querySelector("h3"); - - fetch('index.php?bloc_edit=rename_page_bloc', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({bloc_title: input.value, bloc_id: bloc_id}) - }) - .then(response => response.json()) - .then(data => { - if(data.success){ - title.innerHTML = data.title; - console.log(data.title); - toastNotify('Le bloc a été renommé: ' + data.title); - } - else{ - console.error('Erreur au renommage du titre.'); - } - }) - .catch(error => { - console.error('Erreur:', error); - }); -} - -function switchBlocsPositions(bloc_id, direction, current_page) { - const current_bloc = document.getElementById(bloc_id); - const current_bloc_edit_zone = document.getElementById("bloc_edit_" + bloc_id); - var other_bloc; - - if(direction == 'down'){ - other_bloc = current_bloc.nextElementSibling; - } - else if(direction == 'up'){ - other_bloc = current_bloc.previousElementSibling; - } - - if(other_bloc == null || other_bloc.tagName !== 'SECTION') - { - console.log('Inversion impossible'); - return; - } - const other_bloc_edit_zone = document.getElementById("bloc_edit_" + other_bloc.id); - - fetch('index.php?page=' + current_page + '&bloc_edit=switch_blocs_positions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ id1: bloc_id, id2: parseInt(other_bloc.id) }) - }) - .then(response => response.json()) - .then(data => { - if(data.success) - { - if(direction == 'down'){ - current_bloc.parentElement.insertBefore(other_bloc, current_bloc); - current_bloc_edit_zone.parentElement.insertBefore(other_bloc_edit_zone, current_bloc_edit_zone); - console.log('Inversion réussie'); - } - else if(direction == 'up'){ - other_bloc.parentElement.insertBefore(current_bloc, other_bloc); - other_bloc_edit_zone.parentElement.insertBefore(current_bloc_edit_zone, other_bloc_edit_zone); - console.log('Inversion réussie'); - } - } - else { - - console.error('Échec de l\'inversion'); - } - }) - .catch(error => { - console.error('Erreur:', error); - }); } \ No newline at end of file diff --git a/src/controller/ajax.php b/src/controller/ajax.php index a64c39b..a820136 100644 --- a/src/controller/ajax.php +++ b/src/controller/ajax.php @@ -3,172 +3,9 @@ declare(strict_types=1); -use App\Entity\Article; +use App\Entity\Page; use App\Entity\Node; - -// détection des requêtes de tinymce ou touchant aux articles -if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action'])) -{ - // récupération des données - $data = file_get_contents('php://input'); - $json = json_decode($data, true); - - if($_GET['action'] === 'editor_submit' && isset($json['id']) && isset($json['content'])) - { - if(json_last_error() === JSON_ERROR_NONE) - { - $id = $json['id']; - $director = new Director($entityManager); - - // cas d'une nouvelle "news" - if(is_array($json['content'])){ - foreach($json['content'] as $one_input){ - $one_input = Security::secureString($one_input); - } - $content = $json['content']; - } - else{ - $content = Security::secureString($json['content']); - } - - // nouvel article - if($id[0] === 'n') - { - $section_id = (int)substr($id, 1); // id du bloc
- $director->findNodeById($section_id); - $director->makeSectionNode(); - $node = $director->getNode(); // =
- - if(is_array($content)){ - $date = new \DateTime($content['d']); - $article = new Article($content['i'], $date, $content['t'], $content['p']); - $article_node = new Node('new', 'i' . (string)$date->getTimestamp(), [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); - - // id_node tout juste généré - //$article_node->getId(); - } - else{ - $timestamp = time(); - $date = new \DateTime; - $date->setTimestamp($timestamp); - - $article = new Article($content, $date); // le "current" timestamp est obtenu par la BDD - $article_node = new Node('article', 'i' . (string)$timestamp, [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); - } - - $entityManager->persist($article_node); - $entityManager->flush(); - - echo json_encode(['success' => true, 'article_id' => $article_node->getArticleTimestamp()]); - die; - } - // modification article - else{ - $id[0] = 'i'; // id de l'article node - } - - if($director->makeArticleNode($id)) // une entrée est trouvée - { - $node = $director->getArticleNode(); // article - switch($json['id'][0]){ - case 'i': - $node->getArticle()->setContent($content); - break; - case 'p': - $node->getArticle()->setPreview($content); // html de l'éditeur - break; - case 't': - $node->getArticle()->setTitle($content); // html de l'éditeur - break; - case 'd': - echo json_encode(['success' => false, 'message' => 'l\'action editor_submit ne supporte pas les dates, utiliser date_submit.']); - die; - default: - echo json_encode(['success' => false, 'message' => 'identifiant non utilisable']); - die; - } - $entityManager->flush(); - echo json_encode(['success' => true]); - } - else - { - echo json_encode(['success' => false, 'message' => 'article non identifié']); - } - } - else{ - echo json_encode(['success' => false, 'message' => 'Erreur de décodage JSON']); - } - die; - } - elseif($_GET['action'] === 'delete_article' && isset($json['id'])) - { - $director = new Director($entityManager); - $director->makeArticleNode($json['id'], true); - $article = $director->getArticleNode(); - $section = $director->getNode(); - - $entityManager->remove($article); - $section->removeChild($article); - $section->sortChildren(true); // régénère les positions - $entityManager->flush(); - - // test avec une nouvelle requête qui ne devrait rien trouver - if(!$director->makeArticleNode($json['id'])) - { - echo json_encode(['success' => true]); - - // on pourrait afficher une notification "toast" - } - else{ - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Erreur lors de la suppression de l\'article.']); - } - die; - } - // inversion de la position de deux noeuds - elseif($_GET['action'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) - { - $director = new Director($entityManager); - $director->makeArticleNode($json['id1'], true); - $article1 = $director->getArticleNode(); - $section = $director->getNode(); - - $section->sortChildren(true); // régénère les positions avant inversion - - $article2; - foreach($section->getChildren() as $child){ - if($child->getArticleTimestamp() === $json['id2']) // type string - { - $article2 = $child; - break; - } - } - - // inversion - $tmp = $article1->getPosition(); - $article1->setPosition($article2->getPosition()); - $article2->setPosition($tmp); - $entityManager->flush(); - - echo json_encode(['success' => true]); - die; - } - elseif($_GET['action'] === 'date_submit' && isset($json['id']) && isset($json['date'])) - { - $id = $json['id']; - $id[0] = 'i'; - $date = new DateTime($json['date']); - - $director = new Director($entityManager); - $director->makeArticleNode($id); - $node = $director->getArticleNode(); - $node->getArticle()->setDateTime($date); - $entityManager->flush(); - - echo json_encode(['success' => true]); - die; - } -} +use App\Entity\Article; // détection des requêtes d'upload d'image de tinymce if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image') @@ -207,221 +44,414 @@ if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_ } -/* -- page Menu et chemins -- */ -if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['menu_edit'])) -{ - // récupération des données +// détection des requêtes de type XHR, y en a pas à priori +/*elseif(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){ + echo "requête XHR reçue par le serveur"; + die; +}*/ + + +// détection des requêtes envoyées avec fetch (application/json) et récupération du JSON +if($_SERVER['CONTENT_TYPE'] === 'application/json'){ $data = file_get_contents('php://input'); $json = json_decode($data, true); - Director::$menu_data = new Menu($entityManager); - - // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions - if($_GET['menu_edit'] === 'move_one_level_up' && isset($json['id'])){ - $id = $json['id']; - $page = Director::$menu_data->findPageById((int)$id); - - $parent = $page->getParent(); // peut être null - if($parent === null){ - // 1er niveau: ne rien faire - echo json_encode(['success' => false]); - die; - } - // BDD - else{ - $page->setPosition($parent->getPosition() + 1); // nouvelle position - - // 2ème niveau: le parent devient $menu_data, puis null après tri - if($parent->getParent() === null){ - // connexion dans les deux sens - $page->setParent(Director::$menu_data); // => pour la persistance - - //Director::$menu_data->addChild($page); // => pour sortChildren - $page->getParent()->addChild($page); // => pour sortChildren - //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères - $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères - $page->setParent(null); - - // affichage - $page->setPagePath($page->getEndOfPath()); - $page->fillChildrenPagePath(); - } - // 3ème niveau et plus - else{ - $page->setParent($parent->getParent()); // nouveau parent - $page->getParent()->addChild($page); // => pour sortChildren - $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères - $page->fillChildrenPagePath($page->getParent()->getPagePath()); - } - //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive? - $entityManager->flush(); - - // affichage - $parent->removeChild($page); - $nav_builder = new NavBuilder(); - $menu_builder = new MenuBuilder(null, false); - echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); - die; - } - } - // flèche droite =>: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent - if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){ - $id = $json['id']; - $page = Director::$menu_data->findPageById((int)$id); + // requêtes de tinymce ou touchant aux articles + if(isset($_GET['action'])) + { + if($_GET['action'] === 'editor_submit' && isset($json['id']) && isset($json['content'])) + { + if(json_last_error() === JSON_ERROR_NONE) + { + $id = $json['id']; + $director = new Director($entityManager); + + // cas d'une nouvelle "news" + if(is_array($json['content'])){ + foreach($json['content'] as $one_input){ + $one_input = Security::secureString($one_input); + } + $content = $json['content']; + } + else{ + $content = Security::secureString($json['content']); + } + + // nouvel article + if($id[0] === 'n') + { + $section_id = (int)substr($id, 1); // id du bloc
+ $director->findNodeById($section_id); + $director->makeSectionNode(); + $node = $director->getNode(); // =
+ + if(is_array($content)){ + $date = new \DateTime($content['d']); + $article = new Article($content['i'], $date, $content['t'], $content['p']); + $article_node = new Node('new', 'i' . (string)$date->getTimestamp(), [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); + + // id_node tout juste généré + //$article_node->getId(); + } + else{ + $timestamp = time(); + $date = new \DateTime; + $date->setTimestamp($timestamp); + + $article = new Article($content, $date); // le "current" timestamp est obtenu par la BDD + $article_node = new Node('article', 'i' . (string)$timestamp, [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); + } + + $entityManager->persist($article_node); + $entityManager->flush(); + + echo json_encode(['success' => true, 'article_id' => $article_node->getArticleTimestamp()]); + die; + } + // modification article + else{ + $id[0] = 'i'; // id de l'article node + } + + if($director->makeArticleNode($id)) // une entrée est trouvée + { + $node = $director->getArticleNode(); // article + switch($json['id'][0]){ + case 'i': + $node->getArticle()->setContent($content); + break; + case 'p': + $node->getArticle()->setPreview($content); // html de l'éditeur + break; + case 't': + $node->getArticle()->setTitle($content); // html de l'éditeur + break; + case 'd': + echo json_encode(['success' => false, 'message' => 'l\'action editor_submit ne supporte pas les dates, utiliser date_submit.']); + die; + default: + echo json_encode(['success' => false, 'message' => 'identifiant non utilisable']); + die; + } + $entityManager->flush(); + echo json_encode(['success' => true]); + } + else + { + echo json_encode(['success' => false, 'message' => 'article non identifié']); + } + } + else{ + echo json_encode(['success' => false, 'message' => 'Erreur de décodage JSON']); + } + die; + } + elseif($_GET['action'] === 'delete_article' && isset($json['id'])) + { + $director = new Director($entityManager); + $director->makeArticleNode($json['id'], true); + $article = $director->getArticleNode(); + $section = $director->getNode(); + + $entityManager->remove($article); + $section->removeChild($article); + $section->sortChildren(true); // régénère les positions + $entityManager->flush(); - $parent = $page->getParent(); // peut être null - if($parent == null){ - $parent = Director::$menu_data; - } + // test avec une nouvelle requête qui ne devrait rien trouver + if(!$director->makeArticleNode($json['id'])) + { + echo json_encode(['success' => true]); - // BDD - $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3... - if($page->getPosition() > 1){ - foreach($parent->getChildren() as $child){ - //echo $child->getPageName(); - if($child->getPosition() === $page->getPosition() - 1){ - $page->setParent($child); - break; - } - } - $page->setPosition(count($page->getParent()->getChildren()) + 1); - } - $entityManager->flush(); + // on pourrait afficher une notification "toast" + } + else{ + http_response_code(500); + echo json_encode(['success' => false, 'message' => 'Erreur lors de la suppression de l\'article.']); + } + die; + } + // inversion de la position de deux noeuds + elseif($_GET['action'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) + { + $director = new Director($entityManager); + $director->makeArticleNode($json['id1'], true); + $article1 = $director->getArticleNode(); + $section = $director->getNode(); + + $section->sortChildren(true); // régénère les positions avant inversion + + $article2; + foreach($section->getChildren() as $child){ + if($child->getArticleTimestamp() === $json['id2']) // type string + { + $article2 = $child; + break; + } + } - // affichage - $parent->removeChild($page); - $page->getParent()->addChild($page); - $page->fillChildrenPagePath($page->getParent()->getPagePath()); // variable non mappée $page_path - $nav_builder = new NavBuilder(); - $menu_builder = new MenuBuilder(null, false); + // inversion + $tmp = $article1->getPosition(); + $article1->setPosition($article2->getPosition()); + $article2->setPosition($tmp); + $entityManager->flush(); - echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); - die; + echo json_encode(['success' => true]); + die; + } + elseif($_GET['action'] === 'date_submit' && isset($json['id']) && isset($json['date'])) + { + $id = $json['id']; + $id[0] = 'i'; + $date = new DateTime($json['date']); + + $director = new Director($entityManager); + $director->makeArticleNode($id); + $node = $director->getArticleNode(); + $node->getArticle()->setDateTime($date); + $entityManager->flush(); + + echo json_encode(['success' => true]); + die; + } } - if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) + + /* -- page Menu et chemins -- */ + elseif(isset($_GET['menu_edit'])) { - $id1 = $json['id1']; - $id2 = $json['id2']; - - // vérifier qu'ils ont le même parent - $page1 = Director::$menu_data->findPageById((int)$id1); - $page2 = Director::$menu_data->findPageById((int)$id2); - - // double le contrôle fait en JS - if($page1->getParent() === $page2->getParent()) // comparaison stricte d'objet (même instance du parent?) - { - // inversion - $tmp = $page1->getPosition(); - $page1->setPosition($page2->getPosition()); - $page2->setPosition($tmp); - Director::$menu_data->sortChildren(true); // modifie tableau children + // récupération des données + $data = file_get_contents('php://input'); + $json = json_decode($data, true); + Director::$menu_data = new Menu($entityManager); + + // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions + if($_GET['menu_edit'] === 'move_one_level_up' && isset($json['id'])){ + $id = $json['id']; + $page = Director::$menu_data->findPageById((int)$id); + + $parent = $page->getParent(); // peut être null + if($parent === null){ + // 1er niveau: ne rien faire + echo json_encode(['success' => false]); + die; + } + // BDD + else{ + $page->setPosition($parent->getPosition() + 1); // nouvelle position + + // 2ème niveau: le parent devient $menu_data, puis null après tri + if($parent->getParent() === null){ + // connexion dans les deux sens + $page->setParent(Director::$menu_data); // => pour la persistance + + //Director::$menu_data->addChild($page); // => pour sortChildren + $page->getParent()->addChild($page); // => pour sortChildren + //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères + $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères + $page->setParent(null); + + // affichage + $page->setPagePath($page->getEndOfPath()); + $page->fillChildrenPagePath(); + } + // 3ème niveau et plus + else{ + $page->setParent($parent->getParent()); // nouveau parent + $page->getParent()->addChild($page); // => pour sortChildren + $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères + $page->fillChildrenPagePath($page->getParent()->getPagePath()); + } + //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive? + $entityManager->flush(); + + // affichage + $parent->removeChild($page); + $nav_builder = new NavBuilder(); + $menu_builder = new MenuBuilder(null, false); + echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); + die; + } + } + + // flèche droite =>: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent + if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){ + $id = $json['id']; + $page = Director::$menu_data->findPageById((int)$id); + + $parent = $page->getParent(); // peut être null + if($parent == null){ + $parent = Director::$menu_data; + } + + // BDD + $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3... + if($page->getPosition() > 1){ + foreach($parent->getChildren() as $child){ + if($child->getPosition() === $page->getPosition() - 1){ + $page->setParent($child); + break; + } + } + $page->setPosition(count($page->getParent()->getChildren()) + 1); + } $entityManager->flush(); - - // nouveau menu + + // affichage + $parent->removeChild($page); + $page->getParent()->addChild($page); + $page->fillChildrenPagePath($page->getParent()->getPagePath()); // variable non mappée $page_path $nav_builder = new NavBuilder(); - echo json_encode(['success' => true, 'nav' => $nav_builder->render()]); - } - else{ - echo json_encode(['success' => false]); - } - - die; - } + $menu_builder = new MenuBuilder(null, false); - if($_GET['menu_edit'] === 'displayInMenu' && isset($json['id']) && isset($json['checked'])) - { - $id = $json['id']; - $checked = $json['checked']; + echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]); + die; + } - $page = Director::$menu_data->findPageById((int)$id); - if($page->isHidden() === $checked){ - $page->setHidden(!$checked); - $entityManager->flush(); + if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) + { + $id1 = $json['id1']; + $id2 = $json['id2']; - // nouveau menu - $nav_builder = new NavBuilder(); - echo json_encode(['success' => true, 'nav' => $nav_builder->render()]); + // vérifier qu'ils ont le même parent + $page1 = Director::$menu_data->findPageById((int)$id1); + $page2 = Director::$menu_data->findPageById((int)$id2); + + // double le contrôle fait en JS + if($page1->getParent() === $page2->getParent()) // comparaison stricte d'objet (même instance du parent?) + { + // inversion + $tmp = $page1->getPosition(); + $page1->setPosition($page2->getPosition()); + $page2->setPosition($tmp); + Director::$menu_data->sortChildren(true); // modifie tableau children + $entityManager->flush(); + + // nouveau menu + $nav_builder = new NavBuilder(); + echo json_encode(['success' => true, 'nav' => $nav_builder->render()]); + } + else{ + echo json_encode(['success' => false]); + } + + die; } - else{ - echo json_encode(['success' => false]); + + if($_GET['menu_edit'] === 'displayInMenu' && isset($json['id']) && isset($json['checked'])) + { + $id = $json['id']; + $checked = $json['checked']; + + $page = Director::$menu_data->findPageById((int)$id); + if($page->isHidden() === $checked){ + $page->setHidden(!$checked); + $entityManager->flush(); + + // nouveau menu + $nav_builder = new NavBuilder(); + echo json_encode(['success' => true, 'nav' => $nav_builder->render()]); + } + else{ + echo json_encode(['success' => false]); + } + die; } - die; } -} -/* -- mode Modification d'une page -- */ -if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['bloc_edit'])) -{ - // récupération des données - $data = file_get_contents('php://input'); - $json = json_decode($data, true); + /* -- mode Modification d'une page -- */ - // renommage d'un bloc - if($_GET['bloc_edit'] === 'rename_page_bloc') + // partie "page" + elseif(isset($_GET['page_edit'])) { - if(isset($json['bloc_title']) && $json['bloc_title'] !== null && isset($json['bloc_id']) && is_int($json['bloc_id'])){ - $director = new Director($entityManager); - $director->findNodeById($json['bloc_id']); - - // le titre (du JSON en BDD) est récupéré sous forme de tableau, modifié et renvoyé - $data = $director->getNode()->getNodeData()->getData(); - $data['title'] = htmlspecialchars($json['bloc_title']); - $director->getNode()->getNodeData()->setData($data); - - $entityManager->flush(); - echo json_encode(['success' => true, 'title' => $data['title']]); - } - else{ - echo json_encode(['success' => false]); + // récupération des données + $data = file_get_contents('php://input'); + $json = json_decode($data, true); + + // tite de la page + if($_GET['page_edit'] === 'page_title'){ + $page = $entityManager->find('App\Entity\Page', $json['page_id']); + $page->setPageName(htmlspecialchars($json['title'])); + $entityManager->flush(); + echo json_encode(['success' => true, 'title' => $page->getPageName()]); } - die; - } - // inversion des positions de deux blocs - elseif($_GET['bloc_edit'] === 'switch_blocs_positions') - { - if(isset($json['id1']) && is_int($json['id1']) && isset($json['id2']) && is_int($json['id2']) && isset($_GET['page'])){ - $director = new Director($entityManager, true); - $director->findUniqueNodeByName('main'); - $director->findItsChildren(); - $main = $director->getNode(); - $main->sortChildren(true); // régénère les positions avant inversion - - $bloc1; $bloc2; - foreach($main->getChildren() as $child){ - if($child->getId() === $json['id1']){ - $bloc1 = $child; - break; - } - } - foreach($main->getChildren() as $child){ - if($child->getId() === $json['id2']){ - $bloc2 = $child; - break; - } - } - - // inversion - $tmp = $bloc1->getPosition(); - $bloc1->setPosition($bloc2->getPosition()); - $bloc2->setPosition($tmp); - - $entityManager->flush(); - echo json_encode(['success' => true]); - } - else{ - echo json_encode(['success' => false]); + // titre en snake_case pour le menu + /*elseif($_GET['page_edit'] === 'page_menu_path'){ + $page = $entityManager->find('App\Entity\Page', $json['page_id']); + $page->setEndOfPath(htmlspecialchars($json['page_menu_path'])); + $entityManager->flush(); + echo json_encode(['success' => true, 'page_name_path' => $page->getEndOfPath()]); + }*/ + // description dans les métadonnées + elseif($_GET['page_edit'] === 'page_description'){ + $node_data = $entityManager->find('App\Entity\NodeData', $json['node_data_id']); + $node_data->updateData('description', htmlspecialchars($json['description'])); + $entityManager->flush(); + echo json_encode(['success' => true, 'description' => $node_data->getData()['description']]); } die; - } -} - - -// détection des requêtes de type XHR?, pas d'utilité à priori -/*elseif(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){ - echo "requête XHR reçue par le serveur"; - die; -}*/ - + } + // partie "blocs" + elseif(isset($_GET['bloc_edit'])) + { + // renommage d'un bloc + if($_GET['bloc_edit'] === 'rename_page_bloc') + { + if(isset($json['bloc_title']) && $json['bloc_title'] !== null && isset($json['bloc_id']) && is_int($json['bloc_id'])){ + $director = new Director($entityManager); + $director->findNodeById($json['bloc_id']); + + // le titre (du JSON en BDD) est récupéré sous forme de tableau, modifié et renvoyé + $data = $director->getNode()->getNodeData()->getData(); + $data['title'] = htmlspecialchars($json['bloc_title']); + $director->getNode()->getNodeData()->updateData('title', htmlspecialchars($json['bloc_title'])); + + $entityManager->flush(); + echo json_encode(['success' => true, 'title' => $data['title']]); + } + else{ + echo json_encode(['success' => false]); + } + die; + } + // inversion des positions de deux blocs + elseif($_GET['bloc_edit'] === 'switch_blocs_positions') + { + if(isset($json['id1']) && is_int($json['id1']) && isset($json['id2']) && is_int($json['id2']) && isset($_GET['page'])){ + $director = new Director($entityManager, true); + $director->findUniqueNodeByName('main'); + $director->findItsChildren(); + $main = $director->getNode(); + $main->sortChildren(true); // régénère les positions avant inversion + + $bloc1; $bloc2; + foreach($main->getChildren() as $child){ + if($child->getId() === $json['id1']){ + $bloc1 = $child; + break; + } + } + foreach($main->getChildren() as $child){ + if($child->getId() === $json['id2']){ + $bloc2 = $child; + break; + } + } + + // inversion + $tmp = $bloc1->getPosition(); + $bloc1->setPosition($bloc2->getPosition()); + $bloc2->setPosition($tmp); + + $entityManager->flush(); + echo json_encode(['success' => true]); + } + else{ + echo json_encode(['success' => false]); + } + die; + } + } +} \ No newline at end of file diff --git a/src/controller/installation.php b/src/controller/installation.php index 4aaa4e0..64ed94e 100644 --- a/src/controller/installation.php +++ b/src/controller/installation.php @@ -76,27 +76,29 @@ HTACCESS; // les informations ici ne sont pas demandées à l'utilisateur pour l'instant (on verra ça plus tard) function makeStartPage(EntityManager $entityManager){ /* -- table page -- */ - // paramètres: name_page, end_of_path, reachable, in_menu, position, parent + // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL); - $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); $article = new Page('Article', 'article', true, false, false, NULL, NULL); + $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL); - $edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); + //$edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); // pas de page "Modification de la page" $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL); /* -- table node -- */ // paramètres: name_node, article_timestamp, attributes, position, parent, page, article - $head_accueil = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $accueil, NULL); + $head_accueil = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $accueil, NULL); + $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); $header = new Node('header', NULL, [], 2, NULL, NULL, NULL); $nav = new Node('nav', NULL, [], 1, $header, NULL, NULL); $main = new Node('main', NULL, [], 3, NULL, NULL, NULL); $footer = new Node('footer', NULL, [], 4, NULL, NULL, NULL); $breadcrumb = new Node('breadcrumb', NULL, [], 2, $header, NULL, NULL); - $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav', 'main'], 'js_array' => ['main']], 1, NULL, $connection, NULL); + $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $connection, NULL); $login = new Node('login', NULL, [], 1, $main, $connection, NULL); - $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); - $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'menu'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); - $edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); + $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); + $bloc_edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); + $head_new_page = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'new_page'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); + $bloc_new_page = new Node('new_page', NULL, [], 1, $main, $new_page, NULL); /* -- table image -- */ // paramètres: file_name, file_path, file_path_mini, mime_type, alt @@ -107,20 +109,24 @@ function makeStartPage(EntityManager $entityManager){ $fond_piscine = new Image("fond-piscine.jpg", "assets/fond-piscine.jpg", NULL, "images/jpg", "fond-piscine"); /* -- table node_data -- */ - // paramètres: data, node + // paramètres: data, node, images $head_accueil_data = new NodeData(["description" => "Club, École de natation et Perfectionnement", "title" => "Les Nageurs Bigoudens"], $head_accueil, new ArrayCollection([$favicon])); $header_data = new NodeData(["description" => "Club, École de natation et Perfectionnement", "title" => "Les Nageurs Bigoudens", "facebook_link" => "https://www.facebook.com/nageursbigoudens29120", "instagram_link" => "https://www.instagram.com/nageursbigoudens/"], $header, new ArrayCollection([$logo, $facebook, $instagram, $fond_piscine])); $footer_data = new NodeData(["adresse" => "17, rue Raymonde Folgoas Guillou, 29120 Pont-l’Abbé", "contact_nom" => "Les Nageurs Bigoudens", "e_mail" => "nb.secretariat@orange.fr", "logo_footer" => "assets/logo-nb-et-ffn.png"], $footer); $head_login_data = new NodeData(["description" => "Connexion", "title" => "Connexion"], $head_login, new ArrayCollection([$favicon])); $head_article_data = new NodeData(["description" => "", "title" => ""], $head_article, new ArrayCollection([$favicon])); $head_edit_menu_data = new NodeData(["description" => "Menu et chemins", "title" => "Menu et chemins"], $head_edit_menu, new ArrayCollection([$favicon])); + $head_new_page_data = new NodeData(["description" => "Nouvelle page", "title" => "Nouvelle page"], $head_new_page, new ArrayCollection([$favicon])); + /* -- table page -- */ $entityManager->persist($accueil); - $entityManager->persist($connection); $entityManager->persist($article); + $entityManager->persist($connection); $entityManager->persist($menu_paths); - $entityManager->persist($edit_page); + //$entityManager->persist($edit_page); // pas de page "Modification de la page" $entityManager->persist($new_page); + + /* -- table node -- */ $entityManager->persist($head_accueil); $entityManager->persist($header); $entityManager->persist($nav); @@ -131,20 +137,27 @@ function makeStartPage(EntityManager $entityManager){ $entityManager->persist($login); $entityManager->persist($head_article); $entityManager->persist($head_edit_menu); - $entityManager->persist($edit_menu); + $entityManager->persist($bloc_edit_menu); + $entityManager->persist($head_new_page); + $entityManager->persist($bloc_new_page); + + /* -- table image -- */ $entityManager->persist($favicon); $entityManager->persist($logo); $entityManager->persist($facebook); $entityManager->persist($instagram); $entityManager->persist($fond_piscine); + + /* -- table node_data -- */ $entityManager->persist($head_accueil_data); $entityManager->persist($header_data); $entityManager->persist($footer_data); $entityManager->persist($head_login_data); $entityManager->persist($head_article_data); $entityManager->persist($head_edit_menu_data); - $entityManager->flush(); + $entityManager->persist($head_new_page_data); + $entityManager->flush(); header('Location: ' . new URL); die; } \ No newline at end of file diff --git a/src/controller/post.php b/src/controller/post.php index d437423..631c4ad 100644 --- a/src/controller/post.php +++ b/src/controller/post.php @@ -13,9 +13,30 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) if($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded') { /* -- mode Modification d'une page -- */ + if(isset($_POST['page_menu_path']) && $_POST['page_menu_path'] !== null + && isset($_POST['page_id']) && $_POST['page_id'] !== null + && isset($_POST['page_name_path_hidden']) && $_POST['page_name_path_hidden'] === '') + { + $director = new Director($entityManager, true); + $page = Director::$page_path->getLast(); + //$page = $entityManager->find('App\Entity\Page', $_POST['page_id']); + $path = htmlspecialchars($_POST['page_menu_path']); + // mise en snake_case: filtre caractères non-alphanumériques, minuscule, doublons d'underscore, trim des underscores + $path = trim(preg_replace('/_+/', '_', strtolower(preg_replace('/[^a-zA-Z0-9]/', '_', $path))), '_'); + $page->setEndOfPath($path); + foreach(Director::$menu_data->getChildren() as $child){ + if($child->getEndOfPath() === Director::$page_path->getArray()[0]->getEndOfPath()){ + $child->fillChildrenPagePath(); // MAJ de $page_path + } + } + $entityManager->flush(); + header("Location: " . new URL(['page' => $page->getPagePath(), 'action' => 'modif_page'])); + die; + } // ajout d'un bloc dans une page - if(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null + elseif(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null + && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null && isset($_POST['bloc_title_hidden']) && $_POST['bloc_title_hidden'] === '') // contrôle anti-robot avec input hidden { $director = new Director($entityManager, true); // on a besoin de page_path qui dépend de menu_data @@ -39,6 +60,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) $entityManager->persist($data); $entityManager->flush(); header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page'])); + die; } // suppression d'un bloc de page elseif(isset($_POST['delete_bloc_id']) && $_POST['delete_bloc_id'] !== null @@ -62,8 +84,9 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) $entityManager->remove($bloc); // suppression en BDD $entityManager->flush(); header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page'])); + die; } - + /* -- page Menu et chemins -- */ @@ -91,6 +114,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) $entityManager->persist($page); $entityManager->flush(); header("Location: " . new URL(['page' => $_GET['from']])); + die; } // suppression d'une entrée de menu avec une URL elseif(isset($_POST['delete']) && isset($_POST['x']) && isset($_POST['y'])){ // 2 params x et y sont là parce qu'on a cliqué sur une image @@ -107,9 +131,11 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) $entityManager->remove($page); // suppression en BDD $entityManager->flush(); header("Location: " . new URL(['page' => $_GET['from']])); + die; } else{ header("Location: " . new URL(['error' => 'paramètres inconnus'])); + die; } } diff --git a/src/model/entities/NodeData.php b/src/model/entities/NodeData.php index aaffb6a..8f0f511 100644 --- a/src/model/entities/NodeData.php +++ b/src/model/entities/NodeData.php @@ -43,13 +43,21 @@ class NodeData $this->images = $images; } + public function getId(): int + { + return $this->id_node_data; + } public function getData(): array { return $this->data; } - public function setData(array $data): void + /*public function setData(array $data): void { $this->data = $data; + }*/ + public function updateData(string $key, string $value): void + { + $this->data[$key] = $value; } /*public function setNode(Node $node): void { diff --git a/src/model/entities/Page.php b/src/model/entities/Page.php index 9564342..1ad9ddb 100644 --- a/src/model/entities/Page.php +++ b/src/model/entities/Page.php @@ -71,6 +71,10 @@ class Page { return $this->name_page; } + public function setPageName(string $name): void + { + $this->name_page = $name; + } public function getPagePath(): string { return $this->page_path; @@ -83,6 +87,10 @@ class Page { return $this->end_of_path; } + public function setEndOfPath(string $end_of_path):void + { + $this->end_of_path = $end_of_path; + } public function isReachable(): bool { return $this->reachable; diff --git a/src/view/BreadcrumbBuilder.php b/src/view/BreadcrumbBuilder.php index fcdcd41..c042fa9 100644 --- a/src/view/BreadcrumbBuilder.php +++ b/src/view/BreadcrumbBuilder.php @@ -41,8 +41,8 @@ class BreadcrumbBuilder extends AbstractBuilder $html .= '' . "\n"; } - // fin du chemin - $html .= '' . $breadcrumb_array[$nb_of_entries - 1]->getPageName() . "\n"; + // fin du chemin (=> Thésée) + $html .= '' . $breadcrumb_array[$nb_of_entries - 1]->getPageName() . "\n"; $html .= "\n"; } return $html; diff --git a/src/view/GridBuilder.php b/src/view/GridBuilder.php index 6845c49..30a9040 100644 --- a/src/view/GridBuilder.php +++ b/src/view/GridBuilder.php @@ -69,8 +69,8 @@ class GridBuilder extends AbstractBuilder $content = $this->html; ob_start(); - require $viewFile; - $this->html = ob_get_clean(); // pas de concaténation ici, on écrase + require $viewFile; // utilise $content + $this->html = ob_get_clean(); // nouveau contenu } } } \ No newline at end of file diff --git a/src/view/HeadBuilder.php b/src/view/HeadBuilder.php index 2cca757..4b913b9 100644 --- a/src/view/HeadBuilder.php +++ b/src/view/HeadBuilder.php @@ -28,12 +28,18 @@ class HeadBuilder extends AbstractBuilder { $css .= '' . "\n"; } - $js = ''; + + $js = ''; foreach($js_array as $name) { $js .= '' . "\n"; } + if(MainBuilder::$modif_mode){ + $css .= '' . "\n"; + $js .= '' . "\n"; + } + // tinymce, nécéssite un script de copie dans composer.json if($_SESSION['admin']){ $css .= '' . "\n"; diff --git a/src/view/MainBuilder.php b/src/view/MainBuilder.php index 5096134..11f5c4b 100644 --- a/src/view/MainBuilder.php +++ b/src/view/MainBuilder.php @@ -14,7 +14,7 @@ class MainBuilder extends AbstractBuilder { $this->html .= "
\n"; - // cas particulier de la page article où l'article est greffé sur main + // page article: cas particulier où l'article est greffé sur main if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ // pas censé arriver if(!isset($_GET['id'])){ @@ -42,14 +42,18 @@ class MainBuilder extends AbstractBuilder $this->viewEditBlocks($node); } + // cas normal $this->useChildrenBuilder($node); } $this->html .= "
\n"; } + // mode modification de page uniquement private function viewEditBlocks($node): void { + $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; // mode modification uniquement + // blocs disponibles $blocs = ['Blog', 'Grille', 'Calendrier', 'Galerie']; // générer ça dynamiquement! $blocs_true_names = ['blog', 'grid', 'calendar', 'galery']; @@ -68,41 +72,36 @@ class MainBuilder extends AbstractBuilder ' . "\n";*/ - // création d'un bloc - $this->html .= '
-
-

Ajouter un bloc de page

-
-

-

-

- - -

-
-
' . "\n"; - $this->html .= '
-

Modifier un bloc

'; + //$page_id = Director::$page_path->getLast()->getId(); + $head_node = null; + foreach(ViewBuilder::$root_node->getChildren() as $first_level_node){ + if($first_level_node->getName() === 'head'){ + $head_node = $first_level_node; // normallement c'est le 1er enfant + break; + } + } + + $bloc_edit = ''; foreach($node->getChildren() as $child_node){ // renommage d'un bloc - $this->html .= '
+ $bloc_edit .= '

'. "\n"; // déplacement d'un bloc - $this->html .= ' + $bloc_edit .= ' ' . "\n"; // suppression d'un bloc - $this->html .= '

+ $bloc_edit .= '

'. "\n"; } - $this->html .= "
-
\n"; + + ob_start(); + require $viewFile; + $this->html .= ob_get_clean(); } -} +} \ No newline at end of file diff --git a/src/view/NavBuilder.php b/src/view/NavBuilder.php index f4fb651..fd5f867 100644 --- a/src/view/NavBuilder.php +++ b/src/view/NavBuilder.php @@ -53,7 +53,7 @@ class NavBuilder extends AbstractBuilder { $li_class .= $data->getParent() == null ? 'drop-down' : 'drop-right'; - $nav_html .= '
  • ' . $link . '

    ' . $data->getPageName() . '