diff options
author | polo <ordipolo@gmx.fr> | 2025-09-18 00:27:20 +0200 |
---|---|---|
committer | polo <ordipolo@gmx.fr> | 2025-09-18 00:27:20 +0200 |
commit | fa3c582a2bd91433399a5b275616052028a5a011 (patch) | |
tree | 64a5c2c0eb54dc033fb5ed78ed69745bd492aa05 | |
parent | 027af942de75f7c5bc519fabfa5fa11de9bc89ea (diff) | |
download | cms-fa3c582a2bd91433399a5b275616052028a5a011.zip |
news positionnées en fonction de leur date, suppression de leurs boutons position, améliorations routage page article, bouton share en bas pour les news
-rw-r--r-- | public/css/body.css | 12 | ||||
-rw-r--r-- | public/js/tinymce.js | 6 | ||||
-rw-r--r-- | src/controller/ArticleController.php | 11 | ||||
-rw-r--r-- | src/controller/ViewController.php | 25 | ||||
-rw-r--r-- | src/model/entities/Node.php | 26 | ||||
-rw-r--r-- | src/router.php | 5 | ||||
-rw-r--r-- | src/view/NewBuilder.php | 34 | ||||
-rw-r--r-- | src/view/NewsBlockBuilder.php | 8 | ||||
-rw-r--r-- | src/view/templates/new.php | 1 |
9 files changed, 74 insertions, 54 deletions
diff --git a/public/css/body.css b/public/css/body.css index d60f28c..f8e4f81 100644 --- a/public/css/body.css +++ b/public/css/body.css | |||
@@ -7,10 +7,6 @@ body | |||
7 | background-color: #0cceec; | 7 | background-color: #0cceec; |
8 | } | 8 | } |
9 | 9 | ||
10 | .hidden{ | ||
11 | display: none; | ||
12 | } | ||
13 | |||
14 | #bloc_page | 10 | #bloc_page |
15 | {} | 11 | {} |
16 | 12 | ||
@@ -176,8 +172,7 @@ button .action_icon:hover | |||
176 | } | 172 | } |
177 | .delete_button | 173 | .delete_button |
178 | { | 174 | { |
179 | float: right; | 175 | margin-right: 2px; |
180 | margin-left: 2px; | ||
181 | } | 176 | } |
182 | section button, section input[type=submit] | 177 | section button, section input[type=submit] |
183 | { | 178 | { |
@@ -238,4 +233,9 @@ article a:hover | |||
238 | { | 233 | { |
239 | grid-template-columns: repeat(2, 1fr); | 234 | grid-template-columns: repeat(2, 1fr); |
240 | } | 235 | } |
236 | } | ||
237 | |||
238 | .article_admin_zone p | ||
239 | { | ||
240 | align-self: center; | ||
241 | } \ No newline at end of file | 241 | } \ No newline at end of file |
diff --git a/public/js/tinymce.js b/public/js/tinymce.js index d6b0bf8..81ba8ea 100644 --- a/public/js/tinymce.js +++ b/public/js/tinymce.js | |||
@@ -332,7 +332,11 @@ class Editor | |||
332 | content = this.tiny_instance.getContent(); | 332 | content = this.tiny_instance.getContent(); |
333 | } | 333 | } |
334 | 334 | ||
335 | let fetch_params = {id: this.id, content: content}; | 335 | let fetch_params = { |
336 | id: this.id, | ||
337 | content: content, | ||
338 | from: new URLSearchParams(window.location.search).get('from') // le "$_GET" de javascript | ||
339 | }; | ||
336 | if(this.placement){ | 340 | if(this.placement){ |
337 | fetch_params['placement'] = this.placement; | 341 | fetch_params['placement'] = this.placement; |
338 | } | 342 | } |
diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php index cb132cf..411c1dc 100644 --- a/src/controller/ArticleController.php +++ b/src/controller/ArticleController.php | |||
@@ -36,14 +36,19 @@ class ArticleController | |||
36 | if($json['id'][0] === 'n') // ici $id est un bloc | 36 | if($json['id'][0] === 'n') // ici $id est un bloc |
37 | { | 37 | { |
38 | $section_id = (int)substr($id, 1); // id du bloc <section> | 38 | $section_id = (int)substr($id, 1); // id du bloc <section> |
39 | if(!$director->findNodeById($section_id)){ | 39 | if(!$director->findNodeById($section_id)){ // erreur mauvais id |
40 | echo json_encode(['success' => false, 'error' => 'article_not_saved']); | 40 | echo json_encode(['success' => false, 'error' => 'article_not_saved, bad id']); |
41 | die; | 41 | die; |
42 | } | 42 | } |
43 | $director->makeSectionNode(); | 43 | $director->makeSectionNode(); |
44 | $node = $director->getNode(); // = <section> | 44 | $node = $director->getNode(); // = <section> |
45 | 45 | ||
46 | if(is_array($content)){ // cas d'une nouvelle "news" | 46 | if(is_array($content)){ // cas d'une nouvelle "news" |
47 | if($node->getPage()->getEndOfPath() !== $json['from']){ // erreur mauvais from | ||
48 | echo json_encode(['success' => false, 'error' => 'article_not_saved, bad from']); | ||
49 | die; | ||
50 | } | ||
51 | |||
47 | $date = new \DateTime($content['d'] . ':' . (new \DateTime)->format('s')); // l'input type="datetime-local" ne donne pas les secondes, on les ajoute: 'hh:mm' . ':ss' | 52 | $date = new \DateTime($content['d'] . ':' . (new \DateTime)->format('s')); // l'input type="datetime-local" ne donne pas les secondes, on les ajoute: 'hh:mm' . ':ss' |
48 | $article = new Article($content['i'], $date, $content['t'], $content['p']); | 53 | $article = new Article($content['i'], $date, $content['t'], $content['p']); |
49 | $article_node = new Node('new', [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); | 54 | $article_node = new Node('new', [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); |
diff --git a/src/controller/ViewController.php b/src/controller/ViewController.php index 668fa25..f66baff 100644 --- a/src/controller/ViewController.php +++ b/src/controller/ViewController.php | |||
@@ -33,17 +33,24 @@ class ViewController extends AbstractBuilder // ViewController est aussi le prem | |||
33 | } | 33 | } |
34 | 34 | ||
35 | // page article: mode création et erreurs d'id | 35 | // page article: mode création et erreurs d'id |
36 | if($_SESSION['admin'] && $request->query->has('page') && $request->query->get('page') === 'article'){ | 36 | if($request->query->has('page') && $request->query->get('page') === 'article'){ |
37 | if(!$request->query->has('id')){ | 37 | if($_SESSION['admin']){ |
38 | return new Response($this->html, 302); | 38 | if(!$request->query->has('id')){ |
39 | } | ||
40 | else{ | ||
41 | if($request->query->get('id')[0] === 'n'){ // mode création d'article (vérification de l'id du bloc dans ArticleController) | ||
42 | NewBuilder::$new_article_mode = true; | ||
43 | } | ||
44 | elseif(self::$root_node->getNodeByName('main')->getAdoptedChild() === null){ // id inconnu | ||
45 | return new Response($this->html, 302); | 39 | return new Response($this->html, 302); |
46 | } | 40 | } |
41 | else{ | ||
42 | // mode création d'article | ||
43 | // l'id du bloc et 'from=' sont vérifiés dans ArticleController::editorSubmit | ||
44 | if($request->query->get('id')[0] === 'n' && $request->query->has('from') && !empty($request->query->get('from'))){ | ||
45 | NewBuilder::$new_article_mode = true; | ||
46 | } | ||
47 | elseif(self::$root_node->getNodeByName('main')->getAdoptedChild() === null){ // id inconnu | ||
48 | return new Response($this->html, 302); | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | elseif($request->query->get('id')[0] === 'n'){ // accès page nouvelle article interdit sans être admin | ||
53 | return new Response($this->html, 302); | ||
47 | } | 54 | } |
48 | } | 55 | } |
49 | 56 | ||
diff --git a/src/model/entities/Node.php b/src/model/entities/Node.php index eb73116..c5df8d1 100644 --- a/src/model/entities/Node.php +++ b/src/model/entities/Node.php | |||
@@ -171,7 +171,31 @@ class Node | |||
171 | public function addChild(self $child): void | 171 | public function addChild(self $child): void |
172 | { | 172 | { |
173 | $this->children[] = $child; | 173 | $this->children[] = $child; |
174 | $this->sortChildren(false); | 174 | |
175 | // cas particulier des news: utilise les dates au lieu des positions (les positions existent mais sont ignorées) | ||
176 | if($this->getName() === 'news_block'){ | ||
177 | $this->sortNews($this->getNodeData()->getData()['chrono'] ?? false); // faux = ordre chronologique | ||
178 | } | ||
179 | else{ | ||
180 | $this->sortChildren(false); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | private function sortNews(bool $chrono = false) // affichage du plus récent au plus ancien par défaut | ||
185 | { | ||
186 | // tri par insertion similaire à Position::sortChildren | ||
187 | for($i = 1; $i < count($this->children); $i++){ | ||
188 | $tmp = $this->children[$i]; | ||
189 | $j = $i - 1; | ||
190 | |||
191 | $compare = $chrono ? fn($a, $b) => $a > $b : fn($a, $b) => $a < $b; | ||
192 | |||
193 | while($j >= 0 && $compare($this->children[$j]->getArticle()->getDateTime(), $tmp->getArticle()->getDateTime())){ | ||
194 | $this->children[$j + 1] = $this->children[$j]; | ||
195 | $j--; | ||
196 | } | ||
197 | $this->children[$j + 1] = $tmp; | ||
198 | } | ||
175 | } | 199 | } |
176 | 200 | ||
177 | public function removeChild(self $child): void | 201 | public function removeChild(self $child): void |
diff --git a/src/router.php b/src/router.php index ccab426..8c33d6e 100644 --- a/src/router.php +++ b/src/router.php | |||
@@ -83,8 +83,7 @@ elseif($_SERVER['REQUEST_METHOD'] === 'POST'){ | |||
83 | // requêtes JSON avec fetch() | 83 | // requêtes JSON avec fetch() |
84 | if($_SERVER['CONTENT_TYPE'] === 'application/json') | 84 | if($_SERVER['CONTENT_TYPE'] === 'application/json') |
85 | { | 85 | { |
86 | $data = file_get_contents('php://input'); | 86 | $json = json_decode($request->getContent(), true); // = json_decode(file_get_contents('php://input'), true); |
87 | $json = json_decode($data, true); | ||
88 | 87 | ||
89 | if($request->query->has('action')) | 88 | if($request->query->has('action')) |
90 | { | 89 | { |
@@ -309,7 +308,7 @@ else{ | |||
309 | 308 | ||
310 | /* -- utilisation de la réponse -- */ | 309 | /* -- utilisation de la réponse -- */ |
311 | if(isset($response)){ | 310 | if(isset($response)){ |
312 | // cas des mauvais id de la page article (d'autres cas à prévoir) | 311 | // cas gérés (d'autres sont à prévoir): mauvais id de la page article, accès page création d'article sans être admin |
313 | if($request->isMethod('GET') && $response->getStatusCode() == 302){ // 302 redirection temporaire | 312 | if($request->isMethod('GET') && $response->getStatusCode() == 302){ // 302 redirection temporaire |
314 | header('Location: ' . new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil'])); | 313 | header('Location: ' . new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil'])); |
315 | } | 314 | } |
diff --git a/src/view/NewBuilder.php b/src/view/NewBuilder.php index 9965d15..cd5534b 100644 --- a/src/view/NewBuilder.php +++ b/src/view/NewBuilder.php | |||
@@ -55,7 +55,7 @@ class NewBuilder extends AbstractBuilder | |||
55 | // page article unique | 55 | // page article unique |
56 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ | 56 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ |
57 | $content = $node->getArticle()->getContent(); | 57 | $content = $node->getArticle()->getContent(); |
58 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []) . '"><button>Page<br>précédente</button></a></p>'; | 58 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []) . '"><button>Retour</button></a></p>'; |
59 | } | 59 | } |
60 | else{ | 60 | else{ |
61 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(['page' => 'article', 'id' => $id, 'from' => CURRENT_PAGE]) . '"><button><img class="action_icon" src="assets/book-open.svg">Lire la suite</button></a></p>'; | 61 | $from_to_button = '<p><a class="link_to_article" href="' . new URL(['page' => 'article', 'id' => $id, 'from' => CURRENT_PAGE]) . '"><button><img class="action_icon" src="assets/book-open.svg">Lire la suite</button></a></p>'; |
@@ -82,8 +82,7 @@ class NewBuilder extends AbstractBuilder | |||
82 | $article_buttons = ''; | 82 | $article_buttons = ''; |
83 | $date_buttons = ''; | 83 | $date_buttons = ''; |
84 | $admin_buttons = ''; | 84 | $admin_buttons = ''; |
85 | if($_SESSION['admin']) | 85 | if($_SESSION['admin']){ |
86 | { | ||
87 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ | 86 | if(Director::$page_path->getLast()->getEndOfPath() === 'article'){ |
88 | $title_js = 'onclick="openEditor(\'' . $id_title . '\')"'; | 87 | $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"; | 88 | $modify_title = '<p id="edit-' . $id_title . '"><button ' . $title_js . '><img class="action_icon" src="assets/edit.svg">Titre</button></p>' . "\n"; |
@@ -122,45 +121,34 @@ class NewBuilder extends AbstractBuilder | |||
122 | $delete_article = ''; | 121 | $delete_article = ''; |
123 | // valider la création d'un nouvel article | 122 | // valider la création d'un nouvel article |
124 | $submit_js = 'onclick="submitArticle(\'' . $_GET['id'] . '\')"'; | 123 | $submit_js = 'onclick="submitArticle(\'' . $_GET['id'] . '\')"'; |
125 | $submit_article = '<p id="save-' . $id . '"><button ' . $submit_js . '><img class="action_icon" src="assets/edit.svg"><span class="delete_button">Tout<br>enregistrer</span></button></p>' . "\n"; | 124 | $submit_article = '<p id="save-' . $id . '"><img class="action_icon delete_button" src="assets/save.svg" ' . $submit_js . '></p>' . "\n"; |
126 | } | 125 | } |
127 | // mode article existant | 126 | // mode article existant |
128 | else{ | 127 | else{ |
129 | $url = new URL(['action' => 'delete_article', 'id' => $_GET['id'], 'from' => $_GET['from'] ?? '']); | 128 | $url = new URL(['action' => 'delete_article', 'id' => $_GET['id'], 'from' => $_GET['from'] ?? '']); |
130 | $delete_article = '<form id="delete-' . $id . '" method="post" onsubmit="return confirm(\'Voulez-vous vraiment supprimer cet article ?\');" action="' . $url . '"> | 129 | $delete_article = '<form id="delete-' . $id . '" method="post" action="' . $url . '"> |
131 | <p><button type="submit"> | 130 | <p> |
132 | <img class="action_icon" src="assets/delete-bin.svg"> | 131 | <img src="assets/delete-bin.svg" alt="Supprimer l\'article" class="action_icon" style="cursor: pointer;" onclick="if(confirm(\'Voulez-vous vraiment supprimer cet article ?\')) { this.closest(\'form\').submit(); }" |
133 | <span class="delete_button">Supprimer<br>cet article</span> | 132 | </p> |
134 | </button></p> | 133 | </form>' . "\n"; // this.closest('form').submit() = submit du formulaire avec javascript |
135 | </form>' . "\n"; | ||
136 | $submit_article = ''; | 134 | $submit_article = ''; |
137 | } | 135 | } |
138 | 136 | ||
139 | $admin_buttons = $delete_article . $from_to_button . $submit_article; | 137 | $admin_buttons = $share_button . $delete_article . $submit_article . $from_to_button; |
140 | } | 138 | } |
141 | // autre page | 139 | // autre page |
142 | else{ | 140 | else{ |
143 | $modify_article = '<p id="edit-' . $id . '"></p>' . "\n"; | ||
144 | |||
145 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | ||
146 | $up_button = '<p id="position_up-' . $id . '"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; | ||
147 | |||
148 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | ||
149 | $down_button = '<p id="position_down-' . $id . '"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; | ||
150 | |||
151 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | 141 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; |
152 | $delete_article = '<p id="delete-' . $id . '"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; | 142 | $delete_article = '<p id="delete-' . $id . '"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; |
153 | 143 | ||
154 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"></p>'; | 144 | $close_editor = '<p id="cancel-' . $id . '" class="hidden"></p>'; |
155 | $submit_article = '<p id="submit-' . $id . '" class="hidden"></p>'; | 145 | $submit_article = '<p id="submit-' . $id . '" class="hidden"></p>'; |
156 | 146 | ||
157 | $submit_article = '<p id="submit-' . $id . '" class="hidden"></p>'; | 147 | $admin_buttons = $from_to_button . $share_button . $delete_article . $close_editor . $submit_article; |
158 | |||
159 | $admin_buttons = $from_to_button . $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; | ||
160 | } | 148 | } |
161 | } | 149 | } |
162 | else{ | 150 | else{ |
163 | $admin_buttons = $from_to_button; | 151 | $admin_buttons = $share_button . $from_to_button; |
164 | } | 152 | } |
165 | 153 | ||
166 | ob_start(); | 154 | ob_start(); |
diff --git a/src/view/NewsBlockBuilder.php b/src/view/NewsBlockBuilder.php index 76e42c5..e7bbec9 100644 --- a/src/view/NewsBlockBuilder.php +++ b/src/view/NewsBlockBuilder.php | |||
@@ -41,12 +41,6 @@ class NewsBlockBuilder extends AbstractBuilder | |||
41 | 41 | ||
42 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; | 42 | $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; |
43 | $modify_article = '<p id="edit-' . $id . '" class="hidden"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; | 43 | $modify_article = '<p id="edit-' . $id . '" class="hidden"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; |
44 | |||
45 | $up_js = 'onclick="switchPositions(\'' . $id . '\', \'up\')"'; | ||
46 | $up_button = '<p id="position_up-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-up.svg" ' . $up_js . '></p>' . "\n"; | ||
47 | |||
48 | $down_js = 'onclick="switchPositions(\'' . $id . '\', \'down\')"'; | ||
49 | $down_button = '<p id="position_down-' . $id . '" class="hidden"><img class="action_icon" src="assets/arrow-down.svg" ' . $down_js . '></p>' . "\n"; | ||
50 | 44 | ||
51 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; | 45 | $delete_js = 'onclick="deleteArticle(\'' . $id . '\')"'; |
52 | $delete_article = '<p id="delete-' . $id . '" class="hidden"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; | 46 | $delete_article = '<p id="delete-' . $id . '" class="hidden"><img class="action_icon" src="assets/delete-bin.svg" ' . $delete_js . '></p>' . "\n"; |
@@ -58,7 +52,7 @@ class NewsBlockBuilder extends AbstractBuilder | |||
58 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; | 52 | $submit_article = '<p id="submit-' . $id . '" class="hidden"><button ' . $submit_js . '>Valider</button></p>'; |
59 | 53 | ||
60 | $html = ''; | 54 | $html = ''; |
61 | $admin_buttons = $new_button . $modify_article . $up_button . $down_button . $delete_article . $close_editor . $submit_article; | 55 | $admin_buttons = $new_button . $modify_article . $delete_article . $close_editor . $submit_article; |
62 | 56 | ||
63 | // post vide mis là pour le bouton "Nouvel article" => déplace vers page "article" | 57 | // post vide mis là pour le bouton "Nouvel article" => déplace vers page "article" |
64 | ob_start(); | 58 | ob_start(); |
diff --git a/src/view/templates/new.php b/src/view/templates/new.php index fadf1a2..bda7daf 100644 --- a/src/view/templates/new.php +++ b/src/view/templates/new.php | |||
@@ -2,7 +2,6 @@ | |||
2 | <article> | 2 | <article> |
3 | <div class="new_content" id="<?= $id ?>"> | 3 | <div class="new_content" id="<?= $id ?>"> |
4 | <div class="article_title_zone"> | 4 | <div class="article_title_zone"> |
5 | <?= $share_button ?> | ||
6 | <div class="data" id="<?= $id_title ?>"> | 5 | <div class="data" id="<?= $id_title ?>"> |
7 | <?= $title ?> | 6 | <?= $title ?> |
8 | </div> | 7 | </div> |