From 5e41bea598ff38b3c520b69fd92ee3412e716df2 Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 9 Sep 2025 15:37:50 +0200 Subject: =?UTF-8?q?fin=20de=20l'utilisation=20du=20champ=20article=5Ftimes?= =?UTF-8?q?tamp=20de=20la=20table=20node,=20r=C3=A9solue=20erreur=20lorsqu?= =?UTF-8?q?e=20deux=20news=20sont=20cr=C3=A9=C3=A9es=20dans=20la=20m=C3=AA?= =?UTF-8?q?me=20minute=20(pas=20dans=20la=20m=C3=AAme=20seconde=20par=20co?= =?UTF-8?q?ntre)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/body.css | 2 +- public/js/main.js | 7 ++-- public/js/menu.js | 3 -- public/js/tinymce.js | 8 ++-- src/URL.php | 16 ++++---- src/controller/ArticleController.php | 30 +++++++------- src/controller/Director.php | 6 +-- src/controller/PageManagementController.php | 11 +---- src/installation.php | 30 +++++++------- src/model/entities/Node.php | 10 ++--- src/router.php | 5 ++- src/view/MainBuilder.php | 4 +- src/view/NewBuilder.php | 62 ++++++++++++++++++----------- src/view/PostBuilder.php | 2 +- src/view/templates/new.php | 4 +- 15 files changed, 103 insertions(+), 97 deletions(-) diff --git a/public/css/body.css b/public/css/body.css index af178a8..d60f28c 100644 --- a/public/css/body.css +++ b/public/css/body.css @@ -69,7 +69,7 @@ section > h3 .grid > .section_child { display: grid; /* et c'est tout */ - /*grid-template-columns: repeat(auto-fit, minmax(' . $min_width . 'px, 1fr)); */ /* dans PostBlockBuilder et NewsBlockBuilder */ + /* la règle grid-template-columns est ajoutée dynamiquement par PHP ou JS*/ } .galery_photos { diff --git a/public/js/main.js b/public/js/main.js index 8f2b214..2936ea0 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -80,8 +80,9 @@ document.addEventListener('DOMContentLoaded', () => { // pour pouvoir attraper l // complète les fonctions dans tinymce.js function switchPositions(article_id, direction) { - const current_article = findParentByTagName(document.getElementById(article_id), 'article'); // l'id n'est pas sur la bonne balise - var other_article; + const current_article = findParentByTagName(document.getElementById(article_id), 'article'); // l'id n'est pas toujours sur la même balise + let other_article; + let other_article_id; if(direction == 'down'){ other_article = current_article.nextElementSibling; @@ -90,10 +91,8 @@ function switchPositions(article_id, direction) other_article = current_article.previousElementSibling; } - var other_article_id; try{ other_article_id = other_article.querySelector('div[id]').id; - other_article_id = 'i' + other_article_id.slice(1); // peut mieux faire } catch(error){ console.log('Inversion impossible'); diff --git a/public/js/menu.js b/public/js/menu.js index 7f48ac9..8f1f326 100644 --- a/public/js/menu.js +++ b/public/js/menu.js @@ -15,7 +15,6 @@ function moveOneLevelUp(page_id) .then(data => { if(data.success) { - console.log(data); // affichage nav_zone.innerHTML = ''; nav_zone.insertAdjacentHTML('afterbegin', data.nav); @@ -23,7 +22,6 @@ function moveOneLevelUp(page_id) menu_edit_buttons.insertAdjacentHTML('afterbegin', data.menu_buttons); } else { - console.error('Échec du déplacement'); } }) @@ -49,7 +47,6 @@ function moveOneLevelDown(page_id) .then(data => { if(data.success) { - console.log(data); // affichage nav_zone.innerHTML = ''; nav_zone.insertAdjacentHTML('afterbegin', data.nav); diff --git a/public/js/tinymce.js b/public/js/tinymce.js index 1e16f6e..d6b0bf8 100644 --- a/public/js/tinymce.js +++ b/public/js/tinymce.js @@ -55,7 +55,7 @@ function deleteArticle(id){ { // Supprimer l'article du DOM const articleElement = document.getElementById(id); - articleElement.parentElement.parentElement.remove(); //
est deux niveau au dessus + findParentByTagName(articleElement, 'article').remove(); toastNotify("L'article a été supprimé."); } else{ @@ -106,7 +106,7 @@ class Editor init(){ tinymce.init({ - selector: `#${this.id}`, // avec un # comme dans querySelector + selector: `[id="${this.id}"]`, // écrire [id="246"] au lieu de #246 parce que l'id commence par un chiffre language: 'fr_FR', // téléchargement ici: https://www.tiny.cloud/get-tiny/language-packages/ language_url: 'js/tinymce-langs/fr_FR.js', // ou installer tweeb/tinymce-i18n avec composer license_key: 'gpl', @@ -136,7 +136,7 @@ class Editor if(window.Config.page !== 'article'){ document.getElementById(`position_up-${this.id}`).classList.add('hidden'); document.getElementById(`position_down-${this.id}`).classList.add('hidden'); - document.getElementById(`delete-${('i' + this.id.slice(1))}`).classList.add('hidden'); + document.getElementById(`delete-${this.id}`).classList.add('hidden'); } } }); @@ -259,7 +259,7 @@ class Editor } close(restore_old = true){ - tinymce.remove(`#${this.id}`); // avec un # comme dans querySelector + tinymce.remove(`[id="${this.id}"]`); // comme dans tinymce.init delete editors[this.id]; // Restaurer le contenu d'origine de l'article diff --git a/src/URL.php b/src/URL.php index 689332f..a6d6379 100644 --- a/src/URL.php +++ b/src/URL.php @@ -12,6 +12,13 @@ class URL implements Stringable private array $params; private string $anchor = ''; + public function __construct(array $gets = [], string $anchor = ''){ + $this->params = $gets; + if($anchor != ''){ + $this->setAnchor($anchor); + } + } + // setters statiques static public function setProtocol(string $protocol = 'http'): void { @@ -39,14 +46,7 @@ class URL implements Stringable { self::$path = '/' . ltrim($path, '/'); } - - public function __construct(array $gets = [], string $anchor = ''){ - $this->params = $gets; - if($anchor != ''){ - $this->setAnchor($anchor); - } - } - + //setters normaux public function addParams(array $gets): void { diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php index 5cebad6..cb132cf 100644 --- a/src/controller/ArticleController.php +++ b/src/controller/ArticleController.php @@ -15,6 +15,10 @@ class ArticleController if(json_last_error() === JSON_ERROR_NONE) { $id = $json['id']; + if(in_array($id[0], ['t', 'p', 'i', 'd'])){ + $id = substr($id, 1); + } + $director = new Director($entityManager); $content = $json['content']; @@ -29,7 +33,7 @@ class ArticleController } // nouvel article - if($id[0] === 'n') + if($json['id'][0] === 'n') // ici $id est un bloc { $section_id = (int)substr($id, 1); // id du bloc
if(!$director->findNodeById($section_id)){ @@ -40,9 +44,9 @@ class ArticleController $node = $director->getNode(); // =
if(is_array($content)){ // cas d'une nouvelle "news" - $date = new \DateTime($content['d']); + $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' $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); + $article_node = new Node('new', [], count($node->getChildren()) + 1, $node, $node->getPage(), $article); } else{ // autres cas $timestamp = time(); @@ -50,9 +54,8 @@ class ArticleController $date->setTimestamp($timestamp); $article = new Article($content, $date); // le "current" timestamp est obtenu par la BDD - $placement = $json['placement'] === 'first' ? 0 : count($node->getChildren()) + 1; // - $article_node = new Node('post', 'i' . (string)$timestamp, [], $placement, $node, $node->getPage(), $article); + $article_node = new Node('post', [], $placement, $node, $node->getPage(), $article); if($json['placement'] === 'first'){ $node->addChild($article_node); @@ -63,13 +66,11 @@ class ArticleController $entityManager->persist($article_node); $entityManager->flush(); - echo json_encode(['success' => true, 'article_id' => $article_node->getArticleTimestamp()]); + echo json_encode(['success' => true, 'article_id' => $article_node->getId()]); die; } // modification article - else{ - $id[0] = 'i'; // id de l'article node - } + //else{} if($director->makeArticleNode($id)) // une entrée est trouvée { @@ -87,9 +88,8 @@ class ArticleController 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; + default: // modif article simple (id sans lettre devant) + $node->getArticle()->setContent($content); } $entityManager->flush(); echo json_encode(['success' => true]); @@ -141,10 +141,9 @@ class ArticleController $section = $director->getNode(); $section->sortChildren(true); // régénère les positions avant inversion - $article2 = null; foreach($section->getChildren() as $child){ - if($child->getArticleTimestamp() === $json['id2']) // type string + if((string)$child->getId() === $json['id2']) // type string { $article2 = $child; break; @@ -163,8 +162,7 @@ class ArticleController static public function dateSubmit(EntityManager $entityManager, array $json): void { - $id = $json['id']; - $id[0] = 'i'; + $id = substr($json['id'], 1); $date = new DateTime($json['date']); $director = new Director($entityManager); diff --git a/src/controller/Director.php b/src/controller/Director.php index 6ee0993..8be9b59 100644 --- a/src/controller/Director.php +++ b/src/controller/Director.php @@ -50,7 +50,7 @@ class Director } else // avec $_GET['id'] dans l'URL { - $dql .= ' OR n.article_timestamp = :id'; + $dql .= ' OR n.id_node = :id'; $bulk_data = $this->entityManager ->createQuery($dql) ->setParameter('page', $this->page) @@ -105,10 +105,10 @@ class Director public function makeArticleNode(string $id = '', bool $get_section = false): bool { if($get_section){ - $dql = 'SELECT n, p FROM App\Entity\Node n LEFT JOIN n.parent p WHERE n.article_timestamp = :id'; + $dql = 'SELECT n, p FROM App\Entity\Node n LEFT JOIN n.parent p WHERE n.id_node = :id'; } else{ - $dql = 'SELECT n FROM App\Entity\Node n WHERE n.article_timestamp = :id'; + $dql = 'SELECT n FROM App\Entity\Node n WHERE n.id_node = :id'; } // n est l'article et p son $parent $bulk_data = $this->entityManager diff --git a/src/controller/PageManagementController.php b/src/controller/PageManagementController.php index 75967eb..3d7edde 100644 --- a/src/controller/PageManagementController.php +++ b/src/controller/PageManagementController.php @@ -79,9 +79,7 @@ class PageManagementController $page->setPagePath(ltrim($parent->getPagePath() . '/' . $page->getEndOfPath(), '/')); // noeud "head" - $node = new Node( - 'head', - null, [], + $node = new Node('head', [], 1, // position d'un head = 1 null, // pas de parent $page); @@ -163,12 +161,7 @@ class PageManagementController $entityManager->persist($bulk_data[0]); } - $block = new Node( - $_POST["bloc_select"], - null, [], - $position, - $main, - $page); + $block = new Node($_POST["bloc_select"], [], $position, $main, $page); $data = new NodeData( ['title' => trim(htmlspecialchars($_POST["bloc_title"]))], $block); diff --git a/src/installation.php b/src/installation.php index b251c43..0d68e7b 100644 --- a/src/installation.php +++ b/src/installation.php @@ -101,21 +101,21 @@ function makeStartPage(EntityManager $entityManager){ /* -- table node -- */ // paramètres: name_node, article_timestamp, attributes, position, parent, page, article - $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'], 'js_array' => ['main']], 1, NULL, $connection, NULL); - $login = new Node('login', NULL, [], 1, $main, $connection, NULL); - $head_my_account = new Node('head', NULL, ["stop" => true, 'css_array' => ['body'], 'js_array' => ['main']], 1, NULL, $my_account, NULL); - $user_edit = new Node('user_edit', NULL, [], 1, $main, $my_account, NULL); - $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], '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', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); - $bloc_new_page = new Node('new_page', NULL, [], 1, $main, $new_page, NULL); + $head_accueil = new Node('head', ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $accueil, NULL); + $head_article = new Node('head', ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); + $header = new Node('header', [], 2, NULL, NULL, NULL); + $nav = new Node('nav', [], 1, $header, NULL, NULL); + $main = new Node('main', [], 3, NULL, NULL, NULL); + $footer = new Node('footer', [], 4, NULL, NULL, NULL); + $breadcrumb = new Node('breadcrumb', [], 2, $header, NULL, NULL); + $head_login = new Node('head', ["stop" => true, 'css_array' => ['body'], 'js_array' => ['main']], 1, NULL, $connection, NULL); + $login = new Node('login', [], 1, $main, $connection, NULL); + $head_my_account = new Node('head', ["stop" => true, 'css_array' => ['body'], 'js_array' => ['main']], 1, NULL, $my_account, NULL); + $user_edit = new Node('user_edit', [], 1, $main, $my_account, NULL); + $head_edit_menu = new Node('head', ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); + $bloc_edit_menu = new Node('menu', [], 1, $main, $menu_paths, NULL); + $head_new_page = new Node('head', ['css_array' => ['body', 'head', 'nav', 'new_page', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); + $bloc_new_page = new Node('new_page', [], 1, $main, $new_page, NULL); /* -- table presentation -- */ $fullwidth = new Presentation('fullwidth'); diff --git a/src/model/entities/Node.php b/src/model/entities/Node.php index 7cf395c..eb73116 100644 --- a/src/model/entities/Node.php +++ b/src/model/entities/Node.php @@ -17,7 +17,7 @@ class Node #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: "integer")] - private int $id_node; + private ?int $id_node = null; #[ORM\Column(type: "string", length: 255)] private string $name_node; @@ -52,16 +52,14 @@ class Node private ?NodeData $node_data = null; - // -- fin des attributs destinés à doctrine, début du code utilisateur -- - + // attributs non destinés à doctrine private array $children = []; // tableau de Node private ?self $adopted = null; // = "new" est un enfant de "main" lorsque la page est "article" static private array $default_attributes = ['css_array' => ['body', 'head', 'nav', 'foot'],'js_array' => ['main']]; - public function __construct(string $name = '', ?string $article_timestamp = null, array $attributes = [], int $position = 0, ?self $parent = null, ?Page $page = null, ?Article $article = null) + public function __construct(string $name = '', array $attributes = [], int $position = 0, ?self $parent = null, ?Page $page = null, ?Article $article = null) { $this->name_node = $name; - $this->article_timestamp = $article_timestamp; $this->attributes = $attributes; $this->position = $position; $this->parent = $parent; @@ -70,7 +68,7 @@ class Node } // pfff... - public function getId(): int + public function getId(): ?int { return $this->id_node; } diff --git a/src/router.php b/src/router.php index 326a637..04441a9 100644 --- a/src/router.php +++ b/src/router.php @@ -306,20 +306,23 @@ else{ /* -- utilisation de la réponse -- */ if(isset($response)){ + // cas des mauvais id de la page article (d'autres cas à prévoir) if($request->isMethod('GET') && $response->getStatusCode() == 302){ // 302 redirection temporaire - // ne gère pour l'instant que les mauvais id de la page article header('Location: ' . new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil'])); } + // redirection après traitement de formulaires HTTP elseif($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ $response_data = json_decode(($response)->getContent(), true); $url = new URL(['page' => !empty($_GET['from']) ? $_GET['from'] : 'accueil']); $url->addParams(['success' => $response_data['success'], 'message' => $response_data['message']]); header('Location: ' . $url); } + // affichage d'une page OU requête AJAX else{ $response->send(); } } +// pas utilisation de RESPONSE (cas destiné à disparaître) else{ if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){ header("Location: " . new URL(['error' => 'erreur côté serveur'])); diff --git a/src/view/MainBuilder.php b/src/view/MainBuilder.php index e6fc61a..8a40d82 100644 --- a/src/view/MainBuilder.php +++ b/src/view/MainBuilder.php @@ -23,11 +23,13 @@ class MainBuilder extends AbstractBuilder die; } + // nouvel article if($node->getAdoptedChild() == null){ $date = new \DateTime; $article = new Article('', $date); - $new = new Node('new', 'i' . (string)$date->getTimestamp(), [], 0, null, null, $article); + $new = new Node('new', [], 0, null, null, $article); } + // modification else{ $new = $node->getAdoptedChild(); } diff --git a/src/view/NewBuilder.php b/src/view/NewBuilder.php index 332d92b..9965d15 100644 --- a/src/view/NewBuilder.php +++ b/src/view/NewBuilder.php @@ -9,31 +9,47 @@ class NewBuilder extends AbstractBuilder { static public bool $new_article_mode = false; - public function __construct(Node $node, ) + public function __construct(Node $node) { $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; if(file_exists($viewFile)) { - // id (timestamp) - if(!empty($node->getAttributes())) - { - extract($node->getAttributes()); + if(self::$new_article_mode){ + $id = $_GET['id']; // ici l'id est le nom du block news_block parent + $title = ''; + $preview = ''; + + // lettre au début de l'id: t = title, p = preview, i = article, d = date + $id_title = $id; + $id_title[0] = 't'; + $id_preview = $id; + $id_preview[0] = 'p'; + $id_content = 'i' . $id; + $id_content[0] = 'i'; + $id_date = $id; + $id_date[0] = 'd'; } + else{ + $id = (string)$node->getId(); - // html, date - $title = $node->getArticle()->getTitle(); - $preview = $node->getArticle()->getPreview(); - - // lettre au début de l'id: i = article, p = preview, t = title, d = date - $id = $node->getArticleTimestamp(); - $id_title = $id; - $id_title[0] = 't'; - $id_preview = $id; - $id_preview[0] = 'p'; - $id_date = $id; - $id_date[0] = 'd'; + // id (timestamp) + if(!empty($node->getAttributes())) + { + extract($node->getAttributes()); + } + // html, date + $title = $node->getArticle()->getTitle(); + $preview = $node->getArticle()->getPreview(); + + // lettre au début de l'id: t = title, p = preview, i = article, d = date + $id_title = 't' . $id; + $id_preview = 'p' . $id; + $id_content = 'i' . $id; + $id_date = 'd' . $id; + } + $content = ''; // page article unique @@ -85,12 +101,12 @@ class NewBuilder extends AbstractBuilder $submit_preview = ''; $preview_buttons = '
' . $modify_preview . $close_editor_preview . $submit_preview . '
'; - $article_js = 'onclick="openEditor(\'' . $id . '\')"'; - $modify_article = '

' . "\n"; - $close_js_article = 'onclick="closeEditor(\'' . $id . '\')"'; - $close_editor_article = ''; - $submit_js_article = 'onclick="submitArticle(\'' . $id . '\')"'; - $submit_article = ''; + $article_js = 'onclick="openEditor(\'' . $id_content . '\')"'; + $modify_article = '

' . "\n"; + $close_js_article = 'onclick="closeEditor(\'' . $id_content . '\')"'; + $close_editor_article = ''; + $submit_js_article = 'onclick="submitArticle(\'' . $id_content . '\')"'; + $submit_article = ''; $article_buttons = '
' . $modify_article . $close_editor_article . $submit_article . '
'; $date_js = 'onclick="changeDate(\'' . $id_date . '\', \'article\');'; diff --git a/src/view/PostBuilder.php b/src/view/PostBuilder.php index ae5cc9b..70a2d77 100644 --- a/src/view/PostBuilder.php +++ b/src/view/PostBuilder.php @@ -22,7 +22,7 @@ class PostBuilder extends AbstractBuilder // html $title = $node->getArticle()->getTitle(); $html = $node->getArticle()->getContent(); - $id = $node->getArticleTimestamp(); + $id = (string)$node->getId(); // partage $share_link = new URL(['page' => CURRENT_PAGE], $id); diff --git a/src/view/templates/new.php b/src/view/templates/new.php index 1b25eba..fadf1a2 100644 --- a/src/view/templates/new.php +++ b/src/view/templates/new.php @@ -1,6 +1,6 @@
-
+
@@ -12,7 +12,7 @@
-
+
-- cgit v1.2.3