aboutsummaryrefslogtreecommitdiff
path: root/src/Service/Router.php
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2026-10-23 00:47:32 +0200
committerpolo <ordipolo@gmx.fr>2026-10-23 00:47:32 +0200
commitf27cca08ff786ceff1870147f6d6bad14d71117f (patch)
treed36597a72025313d6faf4ed228755fa267ebe2f6 /src/Service/Router.php
parentc7309f900ef05bd5cb313110ec159b761af394ec (diff)
downloadcms-f27cca08ff786ceff1870147f6d6bad14d71117f.tar.gz
cms-f27cca08ff786ceff1870147f6d6bad14d71117f.tar.bz2
cms-f27cca08ff786ceff1870147f6d6bad14d71117f.zip
dossiers avec majuscule, namespace pour toutes les classes, autoload psr-4, UserDataService::createZip déplacé dans Backup
Diffstat (limited to 'src/Service/Router.php')
-rw-r--r--src/Service/Router.php393
1 files changed, 393 insertions, 0 deletions
diff --git a/src/Service/Router.php b/src/Service/Router.php
new file mode 100644
index 0000000..98cecc5
--- /dev/null
+++ b/src/Service/Router.php
@@ -0,0 +1,393 @@
1<?php
2// src/Service/Router.php
3//
4/* fonctionnement:
5=> 1er test, méthode http GET? POST?
6=> 2ème test, type de contenu:
7"application/x-www-form-urlencoded" = formulaire
8"application/json" = requête AJAX avec fetch()
9"multipart/form-data" = upload d'image par tinymce
10$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' requête AJAX xhs, non utilisée
11=> 3ème test, comme le 2ème test mais uniquement si IS_ADMIN est vrai */
12
13/* classes de réponses pour les contrôleurs
14Response($html, Response::HTTP_OK) page html
15JsonResponse(['success' => true, 'data' => $data]) ajax
16RedirectResponse('index.php?page=login') redirection
17BinaryFileResponse($filePath) téléchargement
18StreamedResponse(function () {echo "ligne 1\n";echo "ligne 2\n";}) gros fichier */
19
20// relire ça à l'occaz:
21// https://symfony.com/doc/current/introduction/from_flat_php_to_symfony.html
22
23declare(strict_types=1);
24
25namespace App\Service;
26
27use Symfony\Component\HttpFoundation\Request;
28use Doctrine\ORM\EntityManager;
29use Symfony\Component\HttpFoundation\JsonResponse;
30use Symfony\Component\HttpFoundation\RedirectResponse;
31use Symfony\Component\HttpFoundation\Response;
32use App\Service\User;
33use App\View\AbstractBuilder;
34use App\Model\Model;
35use App\Model\Menu;
36use App\Controller\UserController;
37use App\Controller\ArticleController;
38use App\Controller\CalendarController;
39use App\Controller\MaintenanceController;
40use App\Controller\ViewController;
41use App\Controller\ContactFormController;
42use App\Controller\ImageUploadController;
43use App\Controller\HeadFootController;
44use App\Controller\MenuAndPathsController;
45use App\Controller\PageManagementController;
46use App\Controller\FileUploadController;
47
48class Router{
49 private Request $request;
50 private EntityManager $entityManager;
51 private string $route = ''; // défaut page d'accueil
52
53 public function __construct(Request $request, EntityManager $entityManager){
54 $this->request = $request;
55 $this->entityManager = $entityManager;
56
57 if(!User::existUsers($entityManager)){ // table "user" vide
58 $this->route = 'no_user';
59 }
60 }
61
62 public function dispatch(): Response
63 {
64 if($this->request->getMethod() === 'GET'){
65 // table "user" vide
66 if($this->route === 'no_user'){
67 ob_start();
68 require AbstractBuilder::VIEWS_PATH . 'user_create.php';
69 return new Response(ob_get_clean());
70 }
71
72 // bouton déconnexion (méthode GET parce que l'utilisateur ne modifie plus de données à partir de là)
73 if($this->request->query->get('action') === 'deconnection'){
74 return UserController::disconnect(); // retourne un RedirectResponse
75 }
76
77 // articles suivants
78 if($this->request->query->get('fetch') === 'next_articles'){
79 return ArticleController::fetch($this->entityManager, $this->request); // retourne un JsonResponse
80 }
81
82 // données du calendrier
83 // création du calendrier ou changement de dates affichées (boutons flèches mais pas changement de vue)
84 if($this->request->query->get('action') === 'get_events'
85 && $this->request->query->has('start') && $this->request->query->has('end') && empty($this->request->getPayload()->all())){ // getPayload ne récupère pas que des POST
86 return CalendarController::getData($this->entityManager);
87 }
88
89 // pages interdites
90 if(!IS_ADMIN && in_array(CURRENT_PAGE, ['menu_paths', 'new_page', 'user_edit', 'emails', 'maintenance'])){
91 return new RedirectResponse((string)new URL);
92 }
93
94 if(IS_ADMIN){
95 if($this->request->query->get('action') === 'get_mysqldump'){
96 return MaintenanceController::getLastDump($this->entityManager);
97 }
98 if($this->request->query->get('action') === 'get_all_media'){
99 return MaintenanceController::getAllMedia();
100 }
101 }
102
103 // affichage d'une page
104 return ViewController::getWebPage($this->entityManager, $this->request);
105 }
106
107
108 elseif($this->request->getMethod() === 'POST'){
109 /* -- contrôleurs appelables par tout le monde -- */
110
111 // table "user" vide
112 if($this->route === 'no_user'){
113 return UserController::createAdminUser($this->entityManager);
114 }
115
116 // requête JSON avec fetch()
117 if($this->request->headers->get('Content-Type') === 'application/json')
118 {
119 $json = json_decode($this->request->getContent(), true); // = json_decode(file_get_contents('php://input'), true);
120
121 // formulaire de contact
122 if($this->request->query->get('action') === 'send_email'){
123 return ContactFormController::sendVisitorEmail($this->entityManager, $json);
124 }
125 /*else{
126 return new JsonResponse(['success' => false, 'error' => 'tu fais quoi là mec?'], JsonResponse::HTTP_BAD_REQUEST);
127 }*/
128 }
129
130 // envoi formulaire HTML
131 elseif($this->request->headers->get('Content-Type') === 'application/x-www-form-urlencoded'){
132 // tentative de connexion
133 if($this->request->query->get('action') === 'connection'){
134 return UserController::connect($this->entityManager);
135 }
136 /*else{
137 return new RedirectResponse((string)new URL(['error' => 'tu fais quoi là mec?']));
138 }*/
139 }
140
141 if(IS_ADMIN){
142 /* -- requêtes AJAX -- */
143
144 // requêtes JSON avec fetch()
145 if($this->request->headers->get('Content-Type') === 'application/json'){
146 $json = json_decode($this->request->getContent(), true); // = json_decode(file_get_contents('php://input'), true);
147
148 if($this->request->query->has('action')){
149 /* -- manipulation des articles -- */
150 if($this->request->query->get('action') === 'editor_submit' && isset($json['id']) && isset($json['content'])){
151 return ArticleController::editorSubmit($this->entityManager, $json);
152 }
153 elseif($this->request->query->get('action') === 'delete_article' && isset($json['id'])){
154 return ArticleController::deleteArticle($this->entityManager, $this->request); // version AJAX
155 }
156 elseif($this->request->query->get('action') === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){
157 return ArticleController::switchPositions($this->entityManager, $json);
158 }
159 elseif($this->request->query->get('action') === 'date_submit' && isset($json['id']) && isset($json['date'])){
160 return ArticleController::dateSubmit($this->entityManager, $json);
161 }
162
163 switch($this->request->query->get('action')){
164 /* -- bloc Formulaire -- */
165 case 'keep_emails':
166 return ContactFormController::keepEmails($this->entityManager, $json);
167 case 'set_retention_period':
168 return ContactFormController::setEmailsRetentionPeriod($this->entityManager, $json);
169 case 'set_email_param':
170 return ContactFormController::setEmailParam($this->entityManager, $json);
171 case 'test_email':
172 return ContactFormController::sendTestEmail($this->entityManager, $json);
173
174 /* -- page emails -- */
175 case 'delete_email':
176 return ContactFormController::deleteEmail($this->entityManager, $json);
177 case 'toggle_sensitive_email':
178 return ContactFormController::toggleSensitiveEmail($this->entityManager, $json);
179
180 /* -- upload d'image dans tinymce par copier-coller -- */
181 // collage de HTML contenant une ou plusieurs balises <img>
182 case 'upload_image_url':
183 return ImageUploadController::uploadImageHtml();
184 // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML
185 case 'upload_image_base64':
186 return ImageUploadController::uploadImageBase64();
187
188 /* -- requêtes spécifiques au calendrier -- */
189 case 'new_event':
190 return CalendarController::newEvent($json, $this->entityManager);
191 case 'update_event':
192 return CalendarController::updateEvent($json, $this->entityManager);
193 case 'remove_event':
194 return CalendarController::removeEvent($json, $this->entityManager);
195
196 /* -- mode maintenance -- */
197 case 'get_logs':
198 return MaintenanceController::getLogs($this->entityManager);
199 case 'erase_logs':
200 return MaintenanceController::eraseLogs($this->entityManager);
201
202 default:
203 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST);
204 }
205 }
206
207 /* -- site entier (header, footer, favicon) -- */
208 elseif($this->request->query->has('head_foot_text')){
209 return HeadFootController::setTextData($this->entityManager, $this->request->query->get('head_foot_text'), $json);
210 }
211 elseif($this->request->query->has('head_foot_social_check')){
212 return HeadFootController::displaySocialNetwork($this->entityManager, $this->request->query->get('head_foot_social_check'), $json);
213 }
214
215 /* -- page Menu et chemins -- */
216 elseif($this->request->query->has('menu_edit')){
217 // ne suit pas la règle, faire ça dans un contrôleur?
218 Model::$menu = new Menu($this->entityManager); // récupération des données
219
220 // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions
221 if($this->request->query->get('menu_edit') === 'move_one_level_up' && isset($json['id'])){
222 return MenuAndPathsController::MoveOneLevelUp($this->entityManager, $json);
223 }
224 // flèche droite =>: position (léments de a fraterie + 1, l'élément précédent devient le parent
225 elseif($this->request->query->get('menu_edit') === 'move_one_level_down' && isset($json['id'])){
226 return MenuAndPathsController::MoveOneLevelDown($this->entityManager, $json);
227 }
228 elseif($this->request->query->get('menu_edit') === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){
229 return MenuAndPathsController::switchPositions($this->entityManager, $json);
230 }
231 elseif($this->request->query->get('menu_edit') === 'display_in_menu' && isset($json['id']) && isset($json['checked'])){
232 return MenuAndPathsController::displayInMenu($this->entityManager, $json);
233 }
234 elseif($this->request->query->get('menu_edit') === 'url_edit' && isset($json['id']) && isset($json['field']) && isset($json['input_data'])){
235 return MenuAndPathsController::editUrl($this->entityManager, $json);
236 }
237 else{
238 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
239 }
240 }
241
242 /* -- mode Modification d'une page -- */
243 // partie "page"
244 elseif($this->request->query->has('page_edit')){
245 switch($this->request->query->get('page_edit')){
246 case 'page_title':
247 return PageManagementController::setPageTitle($this->entityManager, $json);
248 case 'page_description':
249 return PageManagementController::setPageDescription($this->entityManager, $json);
250 default:
251 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
252 }
253 }
254
255 // partie "blocs"
256 elseif($this->request->query->has('bloc_edit')){
257 switch($this->request->query->get('bloc_edit')){
258 case 'rename_page_bloc':
259 return PageManagementController::renameBloc($this->entityManager, $json);
260 case 'switch_blocs_positions':
261 return PageManagementController::SwitchBlocsPositions($this->entityManager, $json, $this->request->query->get('page'));
262 case 'change_articles_order':
263 return PageManagementController::changeArticlesOrder($this->entityManager, $json);
264 case 'change_presentation':
265 return PageManagementController::changePresentation($this->entityManager, $json);
266 case 'change_cols_min_width':
267 return PageManagementController::changeColsMinWidth($this->entityManager, $json);
268 case 'change_pagination_limit':
269 return PageManagementController::changePaginationLimit($this->entityManager, $json);
270 default:
271 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
272 }
273 }
274
275 else{
276 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
277 }
278 }
279
280 /* -- upload avec FormData OU formulaire HTML avec fichier -- */
281 elseif(str_starts_with($this->request->headers->get('Content-Type'), 'multipart/form-data')){ // = $_SERVER['CONTENT_TYPE']
282 // dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur ou glisser-déposer)
283 if($this->request->query->get('action') === 'upload_image_tinymce'){
284 return ImageUploadController::imageUploadTinyMce();
285 }
286 // dans tinymce, des quatre méthodes: bouton "link", drag & drop, html, base64
287 elseif($this->request->query->get('action') === 'upload_file_tinymce'){
288 return FileUploadController::fileUploadTinyMce();
289 }
290 elseif($this->request->query->has('head_foot_image')){
291 return HeadFootController::uploadAsset($this->entityManager, $this->request->query->get('head_foot_image'));
292 }
293
294 /* -- page Maintenance -- */
295 elseif($this->request->query->get('action') === 'restore_database' && $this->request->request->get('hidden') === ''
296 && $this->request->files->has('uploaded_sql')){
297 return MaintenanceController::downloadSQL($this->entityManager, $this->request);
298 }
299 else{
300 // choix ici entre répondre en JSON ou par une redirection, choix du JSON pour pouvoir passer un message
301 return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
302 }
303 }
304
305 /* -- formulaire HTML sans fichier -- */
306 elseif($this->request->headers->get('Content-Type') === 'application/x-www-form-urlencoded'){
307 if($this->request->query->get('action') === 'delete_article' && $this->request->query->has('id')){
308 return ArticleController::deleteArticle($this->entityManager, $this->request); // version formulaire
309 }
310
311 /* -- nouvelle page -- */
312 elseif($this->request->request->get('page_name') !== null
313 && $this->request->request->get('page_name_path') !== null
314 && $this->request->request->get('page_location') !== null
315 && $this->request->request->get('page_description') !== null
316 && $this->request->request->get('new_page_hidden') === ''){
317 return PageManagementController::newPage($this->entityManager, $this->request->request);
318 }
319
320 /* -- suppression d'une page -- */
321 elseif($this->request->request->get('page_id') !== null
322 && $this->request->request->get('submit_hidden') === ''){
323 return PageManagementController::deletePage($this->entityManager, $this->request->request->get('page_id'));
324 }
325
326
327 /* -- mode Modification d'une page -- */
328 // modification du chemins en snake_case
329 elseif($this->request->request->get('page_menu_path') !== null
330 && $this->request->request->get('page_id') !== null
331 && $this->request->request->get('page_name_path_hidden') === ''){
332 return PageManagementController::updatePageMenuPath($this->entityManager, $this->request->request->get('page_menu_path'));
333 }
334 // ajout d'un bloc dans une page
335 elseif($this->request->request->get('bloc_title') !== null
336 && $this->request->request->get('bloc_select') !== null
337 && $this->request->request->get('bloc_title_hidden') === ''){ // contrôle anti-robot avec input hidden
338 return PageManagementController::addBloc($this->entityManager, $this->request);
339 }
340 // suppression d'un bloc de page
341 elseif($this->request->request->get('delete_bloc_id') !== null
342 && $this->request->request->get('delete_bloc_hidden') === ''){ // contrôle anti-robot avec input hidden
343 return PageManagementController::deleteBloc($this->entityManager, $this->request);
344 }
345
346
347 /* -- page Menu et chemins -- */
348 // création d'une entrée de menu avec une URL
349 elseif($this->request->request->has("label_input") && $this->request->request->has("url_input") && $this->request->request->has("location")){
350 return MenuAndPathsController::newUrlMenuEntry($this->entityManager);
351 }
352 // suppression d'une entrée de menu avec une URL
353 elseif($this->request->request->has('delete') && $this->request->request->has('x') && $this->request->request->has('y')){ // 2 params x et y sont là parce qu'on a cliqué sur une image
354 return MenuAndPathsController::deleteUrlMenuEntry($this->entityManager);
355 }
356
357
358 /* -- page Mon compte -- */
359 elseif($this->request->query->get('action') === 'update_username'){
360 return UserController::updateUsername($this->entityManager);
361 }
362 elseif($this->request->query->get('action') === 'update_password'){
363 return UserController::updatePassword($this->entityManager);
364 }
365
366 /* -- page Maintenance -- */
367 elseif($this->request->query->get('action') === 'restore_database' && $this->request->get('hidden') === '' && $this->request->request->has('selected_sql')){
368 return MaintenanceController::handleBackupSelection($this->entityManager, $this->request);
369 }
370
371 // redirection page d'accueil
372 return new RedirectResponse((string)new URL(['error' => 'paramètres inconnus']));
373 }
374
375 // requêtes XMLHttpRequest
376 elseif($this->request->isXmlHttpRequest()){
377 return new JsonResponse(['success' => false]); // noyer le poisson en laissant penser que le site gère les requêtes XHR
378 }
379
380 // POST admin ne matchant pas
381 return new Response('bad parameters', Response::HTTP_BAD_REQUEST); // code 400
382 }
383
384 // POST non-admin ne matchant pas
385 return new Response('bad parameters', Response::HTTP_BAD_REQUEST); // code 400
386 }
387
388 // méthode HTTP inconnue
389 else{
390 return new RedirectResponse((string)new URL(['error' => 'tu fais quoi là mec?']));
391 }
392 }
393} \ No newline at end of file