summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-08-02 17:03:42 +0200
committerpolo <ordipolo@gmx.fr>2025-08-02 17:03:42 +0200
commit9934a32f7e02c484d6b122c9af860ab1ca9b2dca (patch)
treef4f8d621a42104246375c0489e19e4673d726279 /src
parent20e1d288035a274b48f0d2d26f547ad15e99761d (diff)
downloadcms-9934a32f7e02c484d6b122c9af860ab1ca9b2dca.zip
réorganisation 2 requêtes "form": séparation routage et contrôleurs avec des fonctions
Diffstat (limited to 'src')
-rw-r--r--src/controller/ajax_admin.php10
-rw-r--r--src/controller/ajax_email.php (renamed from src/controller/ajax.php)58
-rw-r--r--src/controller/password.php3
-rw-r--r--src/controller/post.php297
-rw-r--r--src/controller/post_functions_admin.php231
-rw-r--r--src/controller/post_router.php120
-rw-r--r--src/view/MainBuilder.php2
7 files changed, 393 insertions, 328 deletions
diff --git a/src/controller/ajax_admin.php b/src/controller/ajax_admin.php
index 2318ac1..b69be77 100644
--- a/src/controller/ajax_admin.php
+++ b/src/controller/ajax_admin.php
@@ -59,9 +59,7 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|
59 return false; // échec après trois tentatives 59 return false; // échec après trois tentatives
60} 60}
61 61
62 62function imageUploadTinyMce(): void
63// détection des requêtes d'upload d'image de tinymce
64if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image')
65{ 63{
66 if(isset($_FILES['file'])){ 64 if(isset($_FILES['file'])){
67 $file = $_FILES['file']; 65 $file = $_FILES['file'];
@@ -101,6 +99,12 @@ if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_
101 } 99 }
102 die; 100 die;
103} 101}
102
103// détection des requêtes d'upload d'image de tinymce
104if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image')
105{
106 imageUploadTinyMce();
107}
104// cas du collage d'un contenu HTML, réception d'une URL, téléchargement par le serveur et renvoie de l'adresse sur le serveur 108// cas du collage d'un contenu HTML, réception d'une URL, téléchargement par le serveur et renvoie de l'adresse sur le serveur
105elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url') 109elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url')
106{ 110{
diff --git a/src/controller/ajax.php b/src/controller/ajax_email.php
index 16a6c1f..1138e04 100644
--- a/src/controller/ajax.php
+++ b/src/controller/ajax_email.php
@@ -6,6 +6,7 @@ declare(strict_types=1);
6use PHPMailer\PHPMailer\PHPMailer; 6use PHPMailer\PHPMailer\PHPMailer;
7use PHPMailer\PHPMailer\Exception; 7use PHPMailer\PHPMailer\Exception;
8use App\Entity\Email; 8use App\Entity\Email;
9use Doctrine\ORM\EntityManager;
9 10
10// mettre ça ailleurs? 11// mettre ça ailleurs?
11function sendEmail(string $recipient, bool $true_email, string $name = '', string $email = '', string $message = ''): bool 12function sendEmail(string $recipient, bool $true_email, string $name = '', string $email = '', string $message = ''): bool
@@ -58,6 +59,35 @@ function sendEmail(string $recipient, bool $true_email, string $name = '', strin
58 } 59 }
59} 60}
60 61
62function submitEmail(array $json, EntityManager $entityManager): void
63{
64 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
65 $captcha_try = isset($json['captcha']) ? Captcha::controlInput($json['captcha']) : 0;
66
67 // contrôles des entrées
68 $name = htmlspecialchars(trim($json['name']));
69 $email = strtolower(htmlspecialchars(trim($json['email'])));
70 $message = htmlspecialchars(trim($json['message']));
71
72 // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur
73 $form_data = $entityManager->find('App\Entity\NodeData', $json['id']);
74 $recipient = $form_data->getData()['email'] ?? Config::$email_dest;
75
76 if($captcha_try != 0 && $captcha_solution != 0 && ($captcha_try === $captcha_solution)
77 && filter_var($email, FILTER_VALIDATE_EMAIL) && isset($json['hidden']) && empty($json['hidden'])
78 && sendEmail($recipient, true, $name, $email, $message))
79 {
80 $db_email = new Email($email, Config::$email_dest, $message);
81 $entityManager->persist($db_email);
82 $entityManager->flush();
83 echo json_encode(['success' => true]);
84 }
85 else{
86 echo json_encode(['success' => false]);
87 }
88 die;
89}
90
61 91
62// détection des requêtes envoyées avec fetch (application/json) et récupération du JSON 92// détection des requêtes envoyées avec fetch (application/json) et récupération du JSON
63if($_SERVER['CONTENT_TYPE'] === 'application/json') 93if($_SERVER['CONTENT_TYPE'] === 'application/json')
@@ -67,33 +97,9 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json')
67 97
68 if(isset($_GET['action'])) 98 if(isset($_GET['action']))
69 { 99 {
70 /* -- bloc Formulaire -- */ 100 // formulaire de contact
71 if($_GET['action'] === 'send_email'){ 101 if($_GET['action'] === 'send_email'){
72 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; 102 submitEmail($json, $entityManager);
73 $captcha_try = isset($json['captcha']) ? Captcha::controlInput($json['captcha']) : 0;
74
75 // contrôles des entrées
76 $name = htmlspecialchars(trim($json['name']));
77 $email = strtolower(htmlspecialchars(trim($json['email'])));
78 $message = htmlspecialchars(trim($json['message']));
79
80 // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur
81 $form_data = $entityManager->find('App\Entity\NodeData', $json['id']);
82 $recipient = $form_data->getData()['email'] ?? Config::$email_dest;
83
84 if($captcha_try != 0 && $captcha_solution != 0 && ($captcha_try === $captcha_solution)
85 && filter_var($email, FILTER_VALIDATE_EMAIL) && isset($json['hidden']) && empty($json['hidden'])
86 && sendEmail($recipient, true, $name, $email, $message))
87 {
88 $db_email = new Email($email, Config::$email_dest, $message);
89 $entityManager->persist($db_email);
90 $entityManager->flush();
91 echo json_encode(['success' => true]);
92 }
93 else{
94 echo json_encode(['success' => false]);
95 }
96 die;
97 } 103 }
98 } 104 }
99} \ No newline at end of file 105} \ No newline at end of file
diff --git a/src/controller/password.php b/src/controller/password.php
index 62b1542..e91cc16 100644
--- a/src/controller/password.php
+++ b/src/controller/password.php
@@ -213,7 +213,7 @@ function connect(LoginBuilder $builder, EntityManager $entityManager)
213} 213}
214 214
215 215
216function changePassword(EntityManager $entityManager) 216function changePassword(EntityManager $entityManager): void
217{ 217{
218 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie 218 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie
219 219
@@ -284,6 +284,7 @@ function changePassword(EntityManager $entityManager)
284 { 284 {
285 $success = false; 285 $success = false;
286 echo($alertJSNewPassword); 286 echo($alertJSNewPassword);
287 //header("Location: " . new URL(['page' => $_GET['from']])); // choisir "location" entre PHP et JS
287 die; 288 die;
288 } 289 }
289 echo($formulaireModifMDP); 290 echo($formulaireModifMDP);
diff --git a/src/controller/post.php b/src/controller/post.php
deleted file mode 100644
index 5d9500b..0000000
--- a/src/controller/post.php
+++ /dev/null
@@ -1,297 +0,0 @@
1<?php
2// src/controller/post.php
3
4declare(strict_types=1);
5
6use App\Entity\Node;
7use App\Entity\NodeData;
8use App\Entity\Page;
9use App\Entity\Image;
10use Doctrine\Common\Collections\ArrayCollection;
11
12if(isset($_GET['action']) && $_GET['action'] === 'deconnexion')
13{
14 disconnect($entityManager);
15}
16elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp')
17{
18 changePassword($entityManager);
19}
20elseif($_SESSION['admin'] && isset($_GET['page']) && isset($_GET['action']) && $_GET['action'] === 'modif_page'
21 && $_GET['page'] !== 'connexion' && $_GET['page'] !== 'article' && $_GET['page'] !== 'nouvelle_page' && $_GET['page'] !== 'menu_chemins')
22{
23 // les contrôles de la 2è ligne devraient utiliser un tableau
24 MainBuilder::$modif_mode = true;
25}
26
27
28/* -- html form -- */
29if($_SERVER['REQUEST_METHOD'] === 'POST'){
30 // POST ordinaires non admin
31
32 // POST ajax non admin
33 require '../src/controller/ajax.php';
34
35 if($_SESSION['admin'] === true)
36 {
37 /* -- formulaires HTML classiques -- */
38 if($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded')
39 {
40 /* -- nouvelle page -- */
41 if(isset($_POST['page_name']) && $_POST['page_name'] !== null
42 && isset($_POST['page_name_path']) && $_POST['page_name_path'] !== null
43 && isset($_POST['page_location']) && $_POST['page_location'] !== null
44 && isset($_POST['page_description']) && $_POST['page_description'] !== null
45 && isset($_POST['new_page_hidden']) && $_POST['new_page_hidden'] === '')
46 {
47 // titre et chemin
48 $director = new Director($entityManager, true);
49 //Director::$menu_data = new Menu($entityManager);
50 $previous_page = Director::$menu_data->findPageById((int)$_POST["page_location"]); // (int) à cause de declare(strict_types=1);
51 $parent = $previous_page->getParent();
52
53 $page = new Page(
54 trim(htmlspecialchars($_POST["page_name"])),
55 trim(htmlspecialchars($_POST["page_name_path"])),
56 true, true, false,
57 $previous_page->getPosition(),
58 $parent); // peut et DOIT être null si on est au 1er niveau
59
60 // on a donné à la nouvelle entrée la même position qu'à la précédente,
61 // addChild l'ajoute à la fin du tableau "children" puis on trie
62 // exemple avec 2 comme position demandée: 1 2 3 4 2 devient 1 2 3 4 5 et la nouvelle entrée sera en 3è position
63 if($parent == null){
64 $parent = Director::$menu_data;
65 }
66 $parent->addChild($page);
67 $parent->reindexPositions();
68
69 $page->setPagePath(ltrim($parent->getPagePath() . '/' . $page->getEndOfPath(), '/'));
70
71 // noeud "head"
72 $node = new Node(
73 'head',
74 null, [],
75 1, // position d'un head = 1
76 null, // pas de parent
77 $page);
78 $node->useDefaultAttributes(); // fichiers CSS et JS
79
80 $data = new NodeData([
81 // pas de titre, il est dans $page
82 'description' => trim(htmlspecialchars($_POST["page_description"]))],
83 $node);
84
85 $bulk_data = $entityManager
86 ->createQuery('SELECT n FROM App\Entity\Image n WHERE n.file_name LIKE :name')
87 ->setParameter('name', '%favicon%')
88 ->getResult();
89 $data->setImages(new ArrayCollection($bulk_data));
90
91 $entityManager->persist($page);
92 $entityManager->persist($node);
93 $entityManager->persist($data);
94 $entityManager->flush();
95
96 // page créée, direction la page en mode modification pour ajouter des blocs
97 header("Location: " . new URL(['page' => $page->getPagePath(), 'action' => 'modif_page']));
98 die;
99 }
100
101 /* -- suppression d'une page -- */
102 elseif(isset($_POST['page_id']) && $_POST['page_id'] !== null
103 && isset($_POST['submit_hidden']) && $_POST['submit_hidden'] === '')
104 {
105 $page = $entityManager->find('App\Entity\Page', (int)$_POST['page_id']);
106 $nodes = $entityManager->getRepository('App\Entity\Node')->findBy(['page' => $page]);
107 $data = [];
108 foreach($nodes as $node){
109 $data[] = $entityManager->getRepository('App\Entity\NodeData')->findOneBy(['node' => $node]);
110 $entityManager->remove($node);
111 }
112 foreach($data as $one_data){
113 $entityManager->remove($one_data);
114 }
115 $entityManager->remove($page); // suppression en BDD
116
117 $entityManager->flush();
118 header("Location: " . new URL);
119 die;
120 }
121
122
123 /* -- mode Modification d'une page -- */
124
125 // modification des titres, chemins et descriptions
126 elseif(isset($_POST['page_menu_path']) && $_POST['page_menu_path'] !== null
127 && isset($_POST['page_id']) && $_POST['page_id'] !== null
128 && isset($_POST['page_name_path_hidden']) && $_POST['page_name_path_hidden'] === '')
129 {
130 $director = new Director($entityManager, true);
131 $page = Director::$page_path->getLast();
132 $path = htmlspecialchars($_POST['page_menu_path']);
133
134 // mise en snake_case: filtre caractères non-alphanumériques, minuscule, doublons d'underscore, trim des underscores
135 $path = trim(preg_replace('/_+/', '_', strtolower(preg_replace('/[^a-zA-Z0-9]/', '_', $path))), '_');
136 $page->setEndOfPath($path);
137 foreach(Director::$menu_data->getChildren() as $child){
138 if($child->getEndOfPath() === Director::$page_path->getArray()[0]->getEndOfPath()){
139 $child->fillChildrenPagePath(); // MAJ de $page_path
140 }
141 }
142 $entityManager->flush();
143 header("Location: " . new URL(['page' => $page->getPagePath(), 'action' => 'modif_page']));
144 die;
145 }
146 // ajout d'un bloc dans une page
147 elseif(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null
148 && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null
149 && isset($_POST['bloc_title_hidden']) && $_POST['bloc_title_hidden'] === '') // contrôle anti-robot avec input hidden
150 {
151 $director = new Director($entityManager, true); // on a besoin de page_path qui dépend de menu_data
152 $page = Director::$page_path->getLast();
153 $director->findUniqueNodeByName('main');
154 $director->findItsChildren();
155 $main = $director->getNode();
156 $position = count($main->getChildren()) + 1; // position dans la fraterie
157
158 $blocks = ['blog', 'grid', 'calendar', 'galery', 'form']; // même liste dans FormBuilder.php
159 if(!in_array($_POST["bloc_select"], $blocks, true)) // 3è param: contrôle du type
160 {
161 header("Location: " . new URL(['page' => $_GET['page'], 'error' => 'bad_bloc_type']));
162 die;
163 }
164
165 if($_POST["bloc_select"] === 'calendar' || $_POST["bloc_select"] === 'form'){
166 $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page AND n.name_node = :name'; // noeud 'head' de la page
167 $bulk_data = $entityManager
168 ->createQuery($dql)
169 ->setParameter('page', $page)
170 ->setParameter('name', 'head')
171 ->getResult();
172
173 if(count($bulk_data) != 1){ // 1 head par page
174 header("Location: " . new URL(['page' => $_GET['page'], 'error' => 'head_node_not_found']));
175 die;
176 }
177
178 $bulk_data[0]->addAttribute('css_array', $_POST["bloc_select"]);
179 if($_POST["bloc_select"] === 'form'){
180 $bulk_data[0]->addAttribute('js_array', $_POST["bloc_select"]);
181 }
182 $entityManager->persist($bulk_data[0]);
183 }
184
185 $bloc = new Node(
186 $_POST["bloc_select"],
187 null, [],
188 $position,
189 $main,
190 $page);
191 $data = new NodeData(
192 ['title' => trim(htmlspecialchars($_POST["bloc_title"]))],
193 $bloc);
194
195 $entityManager->persist($bloc);
196 $entityManager->persist($data);
197 $entityManager->flush();
198 header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page']));
199 die;
200 }
201 // suppression d'un bloc de page
202 elseif(isset($_POST['delete_bloc_id']) && $_POST['delete_bloc_id'] !== null
203 && isset($_POST['delete_bloc_hidden']) && $_POST['delete_bloc_hidden'] === '') // contrôle anti-robot avec input hidden
204 {
205 $director = new Director($entityManager, true);
206 $director->findUniqueNodeByName('main');
207 $director->findItsChildren();
208 //$director->findNodeById((int)$_POST['delete_bloc_id']);
209 $main = $director->getNode();
210 $bloc;
211 foreach($main->getChildren() as $child){
212 if($child->getId() === (int)$_POST['delete_bloc_id']){
213 $bloc = $child;
214 break;
215 }
216 }
217 $main->removeChild($bloc); // réindex le tableau $children au passage
218 $main->reindexPositions();
219
220 $entityManager->remove($bloc); // suppression en BDD
221 $entityManager->flush();
222 header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page']));
223 die;
224 }
225
226
227 /* -- page Menu et chemins -- */
228
229 // création d'une entrée de menu avec une URL
230 elseif(isset($_POST["label_input"]) && isset($_POST["url_input"]) && isset($_POST["location"])){
231 Director::$menu_data = new Menu($entityManager);
232 $previous_page = Director::$menu_data->findPageById((int)$_POST["location"]); // (int) à cause de declare(strict_types=1);
233 $parent = $previous_page->getParent();
234
235 $page = new Page(
236 trim(htmlspecialchars($_POST["label_input"])),
237 filter_var($_POST["url_input"], FILTER_VALIDATE_URL),
238 true, true, false,
239 $previous_page->getPosition(),
240 $parent); // peut et DOIT être null si on est au 1er niveau
241
242 // on a donné à la nouvelle entrée la même position qu'à la précédente,
243 // addChild l'ajoute à la fin du tableau "children" puis on trie
244 // exemple avec 2 comme position demandée: 1 2 3 4 2 devient 1 2 3 4 5 et la nouvelle entrée sera en 3è position
245 if($parent == null){
246 $parent = Director::$menu_data;
247 }
248 $parent->addChild($page); // true pour réindexer les positions en BDD
249 $parent->reindexPositions();
250
251 $entityManager->persist($page);
252 $entityManager->flush();
253 header("Location: " . new URL(['page' => $_GET['from']]));
254 die;
255 }
256 // suppression d'une entrée de menu avec une URL
257 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
258 Director::$menu_data = new Menu($entityManager);
259 $page = Director::$menu_data->findPageById((int)$_POST["delete"]);
260 $parent = $page->getParent();
261 if($parent == null){
262 $parent = Director::$menu_data;
263 }
264
265 $parent->removeChild($page); // suppression de $children avant de trier
266 $parent->reindexPositions();
267
268 $entityManager->remove($page); // suppression en BDD
269 $entityManager->flush();
270 header("Location: " . new URL(['page' => $_GET['from']]));
271 die;
272 }
273 elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp'
274 && isset($_POST['login']) && isset($_POST['old_password']) && isset($_POST['new_password'])
275 && isset($_POST['modify_password_hidden']) && empty($_POST['modify_password_hidden']))
276 {
277 changePassword($entityManager);
278 header("Location: " . new URL(['page' => $_GET['from']]));
279 die;
280 }
281 else{
282 header("Location: " . new URL(['error' => 'paramètres inconnus']));
283 die;
284 }
285 }
286
287 /* -- requêtes AJAX -- */
288 else{
289 require '../src/controller/ajax_admin.php';
290 }
291
292 require '../src/controller/ajax_calendar_admin.php';
293 }
294}
295elseif($_SERVER['REQUEST_METHOD'] === 'GET'){
296 require '../src/controller/ajax_calendar_visitor.php'; // fullcalendar utilise un GET pour récupérer les données
297} \ No newline at end of file
diff --git a/src/controller/post_functions_admin.php b/src/controller/post_functions_admin.php
new file mode 100644
index 0000000..b47850a
--- /dev/null
+++ b/src/controller/post_functions_admin.php
@@ -0,0 +1,231 @@
1<?php
2// src/controller/post_functions_admin.php
3//
4// sera remplacé pas une ou plusieurs classes pour le routeur de symfony
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9use App\Entity\NodeData;
10use App\Entity\Page;
11//use App\Entity\Image;
12use Doctrine\Common\Collections\ArrayCollection;
13use Doctrine\ORM\EntityManager;
14
15
16function newPage(EntityManager $entityManager): void
17{
18 // titre et chemin
19 $director = new Director($entityManager, true);
20 //Director::$menu_data = new Menu($entityManager);
21 $previous_page = Director::$menu_data->findPageById((int)$_POST["page_location"]); // (int) à cause de declare(strict_types=1);
22 $parent = $previous_page->getParent();
23
24 $page = new Page(
25 trim(htmlspecialchars($_POST["page_name"])),
26 trim(htmlspecialchars($_POST["page_name_path"])),
27 true, true, false,
28 $previous_page->getPosition(),
29 $parent); // peut et DOIT être null si on est au 1er niveau
30
31 // on a donné à la nouvelle entrée la même position qu'à la précédente,
32 // addChild l'ajoute à la fin du tableau "children" puis on trie
33 // exemple avec 2 comme position demandée: 1 2 3 4 2 devient 1 2 3 4 5 et la nouvelle entrée sera en 3è position
34 if($parent == null){
35 $parent = Director::$menu_data;
36 }
37 $parent->addChild($page);
38 $parent->reindexPositions();
39
40 $page->setPagePath(ltrim($parent->getPagePath() . '/' . $page->getEndOfPath(), '/'));
41
42 // noeud "head"
43 $node = new Node(
44 'head',
45 null, [],
46 1, // position d'un head = 1
47 null, // pas de parent
48 $page);
49 $node->useDefaultAttributes(); // fichiers CSS et JS
50
51 $data = new NodeData([
52 // pas de titre, il est dans $page
53 'description' => trim(htmlspecialchars($_POST["page_description"]))],
54 $node);
55
56 $bulk_data = $entityManager
57 ->createQuery('SELECT n FROM App\Entity\Image n WHERE n.file_name LIKE :name')
58 ->setParameter('name', '%favicon%')
59 ->getResult();
60 $data->setImages(new ArrayCollection($bulk_data));
61
62 $entityManager->persist($page);
63 $entityManager->persist($node);
64 $entityManager->persist($data);
65 $entityManager->flush();
66
67 // page créée, direction la page en mode modification pour ajouter des blocs
68 header("Location: " . new URL(['page' => $page->getPagePath(), 'action' => 'modif_page']));
69 die;
70}
71
72function deletePage(EntityManager $entityManager): void
73{
74 $page = $entityManager->find('App\Entity\Page', (int)$_POST['page_id']);
75 $nodes = $entityManager->getRepository('App\Entity\Node')->findBy(['page' => $page]);
76 $data = [];
77 foreach($nodes as $node){
78 $data[] = $entityManager->getRepository('App\Entity\NodeData')->findOneBy(['node' => $node]);
79 $entityManager->remove($node);
80 }
81 foreach($data as $one_data){
82 $entityManager->remove($one_data);
83 }
84 $entityManager->remove($page); // suppression en BDD
85
86 $entityManager->flush();
87 header("Location: " . new URL);
88 die;
89}
90
91function pageMenuPathUpdate(EntityManager $entityManager): void
92{
93 $director = new Director($entityManager, true);
94 $page = Director::$page_path->getLast();
95 $path = htmlspecialchars($_POST['page_menu_path']);
96
97 // mise en snake_case: filtre caractères non-alphanumériques, minuscule, doublons d'underscore, trim des underscores
98 $path = trim(preg_replace('/_+/', '_', strtolower(preg_replace('/[^a-zA-Z0-9]/', '_', $path))), '_');
99 $page->setEndOfPath($path);
100 foreach(Director::$menu_data->getChildren() as $child){
101 if($child->getEndOfPath() === Director::$page_path->getArray()[0]->getEndOfPath()){
102 $child->fillChildrenPagePath(); // MAJ de $page_path
103 }
104 }
105 $entityManager->flush();
106 header("Location: " . new URL(['page' => $page->getPagePath(), 'action' => 'modif_page']));
107 die;
108}
109
110function addBloc(EntityManager $entityManager): void
111{
112 $director = new Director($entityManager, true); // on a besoin de page_path qui dépend de menu_data
113 $page = Director::$page_path->getLast();
114 $director->findUniqueNodeByName('main');
115 $director->findItsChildren();
116 $main = $director->getNode();
117 $position = count($main->getChildren()) + 1; // position dans la fraterie
118
119 $blocks = ['blog', 'grid', 'calendar', 'galery', 'form']; // même liste dans FormBuilder.php
120 if(!in_array($_POST["bloc_select"], $blocks, true)) // 3è param: contrôle du type
121 {
122 header("Location: " . new URL(['page' => $_GET['page'], 'error' => 'bad_bloc_type']));
123 die;
124 }
125
126 if($_POST["bloc_select"] === 'calendar' || $_POST["bloc_select"] === 'form'){
127 $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page AND n.name_node = :name'; // noeud 'head' de la page
128 $bulk_data = $entityManager
129 ->createQuery($dql)
130 ->setParameter('page', $page)
131 ->setParameter('name', 'head')
132 ->getResult();
133
134 if(count($bulk_data) != 1){ // 1 head par page
135 header("Location: " . new URL(['page' => $_GET['page'], 'error' => 'head_node_not_found']));
136 die;
137 }
138
139 $bulk_data[0]->addAttribute('css_array', $_POST["bloc_select"]);
140 if($_POST["bloc_select"] === 'form'){
141 $bulk_data[0]->addAttribute('js_array', $_POST["bloc_select"]);
142 }
143 $entityManager->persist($bulk_data[0]);
144 }
145
146 $bloc = new Node(
147 $_POST["bloc_select"],
148 null, [],
149 $position,
150 $main,
151 $page);
152 $data = new NodeData(
153 ['title' => trim(htmlspecialchars($_POST["bloc_title"]))],
154 $bloc);
155
156 $entityManager->persist($bloc);
157 $entityManager->persist($data);
158 $entityManager->flush();
159 header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page']));
160 die;
161}
162
163function deleteBloc(EntityManager $entityManager): void
164{
165 $director = new Director($entityManager, true);
166 $director->findUniqueNodeByName('main');
167 $director->findItsChildren();
168 //$director->findNodeById((int)$_POST['delete_bloc_id']);
169 $main = $director->getNode();
170 $bloc = null;
171 foreach($main->getChildren() as $child){
172 if($child->getId() === (int)$_POST['delete_bloc_id']){
173 $bloc = $child;
174 break;
175 }
176 }
177 if(!empty($bloc)){ // si $bloc est null c'est que le HTML a été modifié volontairement
178 $main->removeChild($bloc); // réindex le tableau $children au passage
179 $main->reindexPositions();
180 $entityManager->remove($bloc); // suppression en BDD
181 $entityManager->flush();
182 }
183 header("Location: " . new URL(['page' => $_GET['page'], 'action' => 'modif_page']));
184 die;
185}
186
187function newUrlMenuEntry(EntityManager $entityManager): void
188{
189 Director::$menu_data = new Menu($entityManager);
190 $previous_page = Director::$menu_data->findPageById((int)$_POST["location"]); // (int) à cause de declare(strict_types=1);
191 $parent = $previous_page->getParent();
192
193 $page = new Page(
194 trim(htmlspecialchars($_POST["label_input"])),
195 filter_var($_POST["url_input"], FILTER_VALIDATE_URL),
196 true, true, false,
197 $previous_page->getPosition(),
198 $parent); // peut et DOIT être null si on est au 1er niveau
199
200 // on a donné à la nouvelle entrée la même position qu'à la précédente,
201 // addChild l'ajoute à la fin du tableau "children" puis on trie
202 // exemple avec 2 comme position demandée: 1 2 3 4 2 devient 1 2 3 4 5 et la nouvelle entrée sera en 3è position
203 if($parent == null){
204 $parent = Director::$menu_data;
205 }
206 $parent->addChild($page); // true pour réindexer les positions en BDD
207 $parent->reindexPositions();
208
209 $entityManager->persist($page);
210 $entityManager->flush();
211 header("Location: " . new URL(['page' => $_GET['from']]));
212 die;
213}
214
215function deleteUrlMenuEntry(EntityManager $entityManager): void
216{
217 Director::$menu_data = new Menu($entityManager);
218 $page = Director::$menu_data->findPageById((int)$_POST["delete"]);
219 $parent = $page->getParent();
220 if($parent == null){
221 $parent = Director::$menu_data;
222 }
223
224 $parent->removeChild($page); // suppression de $children avant de trier
225 $parent->reindexPositions();
226
227 $entityManager->remove($page); // suppression en BDD
228 $entityManager->flush();
229 header("Location: " . new URL(['page' => $_GET['from']]));
230 die;
231} \ No newline at end of file
diff --git a/src/controller/post_router.php b/src/controller/post_router.php
new file mode 100644
index 0000000..e71852a
--- /dev/null
+++ b/src/controller/post_router.php
@@ -0,0 +1,120 @@
1<?php
2// src/controller/post_router.php
3//
4// routage des requêtes des formulaires et AJAX
5// n'utilisent que des POST à l'exception d'un GET par fullcalendar
6// les contrôleurs des formulaires sont appelés ici,
7// ceux des requêtes AJAX sont derrière d'autres routeurs
8
9declare(strict_types=1);
10
11
12/* appel des contrôleurs dans password.php */
13if(isset($_GET['action']) && $_GET['action'] === 'deconnexion')
14{
15 disconnect($entityManager);
16}
17elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp')
18{
19 changePassword($entityManager);
20}
21
22
23if($_SERVER['REQUEST_METHOD'] === 'POST'){
24 /* -- contrôleurs appellables par tout le monde -- */
25 // POST "ajax"
26 require '../src/controller/ajax_email.php';
27
28 // POST "form"
29 // ...
30
31
32 if($_SESSION['admin'] === true)
33 {
34 /* -- requêtes "form" -- */
35 if($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded') // moyen approximatif de distinguer les requêtes de formulaires et AJAX
36 {
37 require '../src/controller/post_functions_admin.php';
38
39 /* -- nouvelle page -- */
40 if(isset($_POST['page_name']) && $_POST['page_name'] !== null
41 && isset($_POST['page_name_path']) && $_POST['page_name_path'] !== null
42 && isset($_POST['page_location']) && $_POST['page_location'] !== null
43 && isset($_POST['page_description']) && $_POST['page_description'] !== null
44 && isset($_POST['new_page_hidden']) && $_POST['new_page_hidden'] === '')
45 {
46 newPage($entityManager);
47 }
48
49 /* -- suppression d'une page -- */
50 elseif(isset($_POST['page_id']) && $_POST['page_id'] !== null
51 && isset($_POST['submit_hidden']) && $_POST['submit_hidden'] === '')
52 {
53 deletePage($entityManager);
54 }
55
56
57 /* -- mode Modification d'une page -- */
58
59 // modification du chemins en snake_case
60 elseif(isset($_POST['page_menu_path']) && $_POST['page_menu_path'] !== null
61 && isset($_POST['page_id']) && $_POST['page_id'] !== null
62 && isset($_POST['page_name_path_hidden']) && $_POST['page_name_path_hidden'] === '')
63 {
64 pageMenuPathUpdate($entityManager);
65 }
66 // ajout d'un bloc dans une page
67 elseif(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null
68 && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null
69 && isset($_POST['bloc_title_hidden']) && $_POST['bloc_title_hidden'] === '') // contrôle anti-robot avec input hidden
70 {
71 addBloc($entityManager);
72 }
73 // suppression d'un bloc de page
74 elseif(isset($_POST['delete_bloc_id']) && $_POST['delete_bloc_id'] !== null
75 && isset($_POST['delete_bloc_hidden']) && $_POST['delete_bloc_hidden'] === '') // contrôle anti-robot avec input hidden
76 {
77 deleteBloc($entityManager);
78 }
79
80
81 /* -- page Menu et chemins -- */
82
83 // création d'une entrée de menu avec une URL
84 elseif(isset($_POST["label_input"]) && isset($_POST["url_input"]) && isset($_POST["location"])){
85 newUrlMenuEntry($entityManager);
86 }
87 // suppression d'une entrée de menu avec une URL
88 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
89 deleteUrlMenuEntry($entityManager);
90 }
91
92 // modification du mot de passe
93 elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp'
94 && isset($_POST['login']) && isset($_POST['old_password']) && isset($_POST['new_password'])
95 && isset($_POST['modify_password_hidden']) && empty($_POST['modify_password_hidden']))
96 {
97 changePassword($entityManager);
98 }
99 else{
100 header("Location: " . new URL(['error' => 'paramètres inconnus']));
101 die;
102 }
103 }
104
105 /* -- requêtes AJAX -- */
106 else{
107 require '../src/controller/ajax_admin.php';
108 require '../src/controller/ajax_calendar_admin.php';
109 }
110 }
111}
112// cas particulier d'un GET ajax non-admin par fullcalendar
113elseif($_SERVER['REQUEST_METHOD'] === 'GET'){
114 // non-admin
115 require '../src/controller/ajax_calendar_visitor.php';
116
117 if($_SESSION['admin'] === true){
118 // ...
119 }
120} \ No newline at end of file
diff --git a/src/view/MainBuilder.php b/src/view/MainBuilder.php
index 4bd79c3..7f3a0f0 100644
--- a/src/view/MainBuilder.php
+++ b/src/view/MainBuilder.php
@@ -107,7 +107,7 @@ class MainBuilder extends AbstractBuilder
107 $bloc_edit .= '<form method="post" action="' . new URL(['page' => CURRENT_PAGE]) . '"> 107 $bloc_edit .= '<form method="post" action="' . new URL(['page' => CURRENT_PAGE]) . '">
108 <input type="hidden" name="delete_bloc_id" value="' . $child_node->getId() . '"> 108 <input type="hidden" name="delete_bloc_id" value="' . $child_node->getId() . '">
109 <input type="hidden" name="delete_bloc_hidden"> 109 <input type="hidden" name="delete_bloc_hidden">
110 <input type="submit" value="Supprimer" onclick="return confirm(\'Voulez-vous vraiment supprimer cette page?\');"></p> 110 <input type="submit" value="Supprimer" onclick="return confirm(\'Voulez-vous vraiment supprimer ce bloc?\');"></p>
111 </form> 111 </form>
112 </div>'. "\n"; 112 </div>'. "\n";
113 } 113 }