From 15cbf5d56b4644151d59fee512f5f8fbe496caa3 Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 9 Oct 2025 01:35:52 +0200 Subject: pagination partie 2, nouvelles fonctions + renommage dans Director, ArticleController::fetch, et en JS: fetchArticles, insertLocalDates, modifs dans changePaginationLimit, dans les vues --- src/controller/ArticleController.php | 41 +++++++++ src/controller/Director.php | 132 ++++++++++++++++------------ src/controller/PageManagementController.php | 17 ++++ 3 files changed, 135 insertions(+), 55 deletions(-) (limited to 'src/controller') diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php index 411c1dc..8bbef19 100644 --- a/src/controller/ArticleController.php +++ b/src/controller/ArticleController.php @@ -6,10 +6,51 @@ declare(strict_types=1); use App\Entity\Node; use App\Entity\Article; use Doctrine\ORM\EntityManager; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ArticleController { + static public function fetch(EntityManager $entityManager, Request $request): void + { + if($request->query->has('id') && !empty($request->query->get('id')) && $request->query->has('last_article')){ + //var_dump($request->query->get('last_article')); + $id = (int)$request->get('id'); // type et nettoie + $director = new Director($entityManager); + $director->findNodeById($id); + $parent_block = $director->getNode(); + + if(Blocks::hasPresentation($parent_block->getName())){ + $get_articles_return = $director->getNextArticles($parent_block, $request); + $bulk_data = $get_articles_return[0]; + + if($parent_block->getName() === 'post_block'){ + $builder_name = 'PostBuilder'; + } + elseif($parent_block->getName() === 'news_block'){ + $builder_name = 'NewBuilder'; + } + + $html = ''; + foreach($bulk_data as $article){ + $builder = new $builder_name($article); + $html .= $builder->render(); + } + + echo json_encode(['success' => true, 'html' => $html, 'truncated' => $get_articles_return[1]]); + die; + } + else{ + echo json_encode(['success' => false, 'error' => 'mauvais type de bloc']); + die; + } + } + else{ + echo json_encode(['success' => false, 'error' => 'la requête ne comporte pas les paramètres attendus']); + die; + } + } + static public function editorSubmit(EntityManager $entityManager, array $json): void { if(json_last_error() === JSON_ERROR_NONE) diff --git a/src/controller/Director.php b/src/controller/Director.php index 8f038fa..9c1c6e3 100644 --- a/src/controller/Director.php +++ b/src/controller/Director.php @@ -1,12 +1,14 @@ src/model/Model.php serait mieux + declare(strict_types=1); use Doctrine\ORM\EntityManager; use App\Entity\Page; use App\Entity\Node; -//use Doctrine\ORM\QueryBuilder; +use Doctrine\ORM\QueryBuilder; use Symfony\Component\HttpFoundation\Request; class Director @@ -24,7 +26,9 @@ class Director $this->node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants } - public function makeMenuAndPaths(): void + // à déplacer dans Path ou un truc comme ça? + // couper Director en deux classes NodeModel et PageModel? + public function makeMenuAndPaths(): void // lit la table "page" { self::$menu_data = new Menu($this->entityManager); self::$page_path = new Path(); @@ -41,13 +45,12 @@ class Director } // affichage d'une page ordinaire - public function getWholePageData(Request $request): void + public function getWholePageData(Request $request): void // lit la table "node" + jointures { $id = CURRENT_PAGE === 'article' ? htmlspecialchars($request->query->get('id')) : ''; - if($id === '') // page "normale" - { - // tous les noeuds sauf les articles, tri par page + if($id === ''){ // page "normale" + // récupérer tous les noeuds sauf les articles $dql = "SELECT n FROM App\Entity\Node n WHERE n.name_node != 'new' AND n.name_node != 'post' AND (n.page = :page OR n.page IS null)"; $bulk_data = $this->entityManager ->createQuery($dql) @@ -57,45 +60,11 @@ class Director // groupes d'articles triés par bloc, permet de paginer par bloc foreach($bulk_data as $parent_block){ if(Blocks::hasPresentation($parent_block->getName())){ // = post_block ou news_block - $qb = $this->entityManager->createQueryBuilder(); - $qb->select('n') - ->from('App\Entity\Node', 'n') - ->where('n.parent = :parent') - ->setParameter('parent', $parent_block); - - if($parent_block->getName() === 'post_block'){ - $qb->orderBy('n.position'); - } - elseif($parent_block->getName() === 'news_block'){ - $qb->join('n.article', 'a'); - if($parent_block->getNodeData()->getChronoOrder() ?? false){ // ordre antichrono par défaut - $qb->orderBy('a.date_time', 'ASC'); - } - else{ - $qb->orderBy('a.date_time', 'DESC'); - } - } - - // pagination - $limit = $parent_block->getNodeData()->getPaginationLimit() ?? 0; // 0 par défaut = pas de pagination, sinon 12 rend bien avec des grilles de 2, 3 ou 4 colonnes - if($limit > 0){ - //$this->paginateWithCursor($qb, $request->query->get('last_position') ?? 0, $limit); - $qb->andWhere('n.position > :last_position') - ->setParameter('last_position', $request->query->get('last_position') ?? 0) - ->setMaxResults($limit); - - $nb_pages = $this->getNumberOfPages($parent_block, $limit); // nombres de "pages" d'articles - if($nb_pages > 1){ - //$parent_block->setNumberOfPages($nb_pages); // => navigation en HTML - } - } - - $bulk_data = array_merge($bulk_data, $qb->getQuery()->getResult()); + $bulk_data = array_merge($bulk_data, $this->getNextArticles($parent_block, $request)[0]); } } } - else // page "article" - { + else{ // page "article" $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page OR n.page IS null OR n.id_node = :id'; $bulk_data = $this->entityManager ->createQuery($dql) @@ -103,18 +72,74 @@ class Director ->setParameter('id', $id) ->getResult(); } + $this->makeNodeTree($bulk_data); } - /*private function paginateWithCursor(QueryBuilder $qb, int $last_position = 0, int $limit = 0): void + // récupération d'articles + public function getNextArticles(Node $parent_block, Request $request): array + { + $qb = $this->entityManager->createQueryBuilder(); + $qb->select('n') + ->from('App\Entity\Node', 'n') + ->where('n.parent = :parent') + ->setParameter('parent', $parent_block); + + if($parent_block->getName() === 'post_block'){ + $qb->orderBy('n.position'); + } + elseif($parent_block->getName() === 'news_block'){ + $qb->join('n.article', 'a'); + if($parent_block->getNodeData()->getChronoOrder() ?? false){ // ordre antichrono par défaut + $qb->orderBy('a.date_time', 'ASC'); + } + else{ + $qb->orderBy('a.date_time', 'DESC'); + } + } + + // pagination + $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD + $this->paginateWithCursor($qb, $parent_block, $request->query->get('last_article')); + $result = $qb->getQuery()->getResult(); + + // il reste des articles à récupérer SI on vient d'en récupérer trop + // ET on gère le cas particulier de $limit <= 0 + $truncated = false; + if(count($result) > $limit && $limit > 0){ // si nb résultat > limit > 0 + $truncated = true; + array_pop($result); // compenser le $limit + 1 dans paginateWithCursor + } + + return [$result, $truncated]; // besoin exceptionnel de retourner deux valeurs + } + + private function paginateWithCursor(QueryBuilder $qb, Node $parent_block, ?string $last_article): void { - $qb->andWhere('n.position > :last_position') - ->setParameter('last_position', $last_position) - ->setMaxResults($limit); - }*/ + //var_dump($last_article); + $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD + + if($limit > 0){ // si 0 ou moins pas de pagination + // nombres de "pages" d'articles + $nb_pages = $this->getNumberOfPages($parent_block, $limit); + $parent_block->getNodeData()->setNumberOfPages($nb_pages > 1 ? $nb_pages : 1); + + // adaptation de la requête + if($parent_block->getName() === 'post_block'){ + $qb->andWhere('n.position > :last_position') + ->setParameter('last_position', empty($last_article) ? 0 : $last_article) + ->setMaxResults($limit + 1); + } + elseif($parent_block->getName() === 'news_block'){ + $cursor_start = $parent_block->getNodeData()->getChronoOrder() ? '1970-01-01' : '9999-12-31'; + $qb->andWhere($parent_block->getNodeData()->getChronoOrder() ? 'a.date_time > :date_time' : 'a.date_time < :date_time') + ->setParameter('date_time', empty($last_article) ? $cursor_start : $last_article) + ->setMaxResults($limit + 1); + } + } + } - // requête à part n'alimentant pas $bulk_data - // fonctionnalité offerte par le Paginator de doctrine si on décidait de s'en servir + // le Paginator de doctrine le fait aussi si on décidait de s'en servir private function getNumberOfPages(Node $parent_block, int $limit): int { $dql = 'SELECT COUNT(n.id_node) FROM App\Entity\Node n WHERE n.parent = :parent'; @@ -129,11 +154,9 @@ class Director { // puis on les range // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD) - foreach($bulk_data as $node) - { + foreach($bulk_data as $node){ // premier niveau - if($node->getParent() == null) - { + if($node->getParent() == null){ $this->node->addChild($node); // spécifique page article @@ -142,8 +165,7 @@ class Director } } // autres niveaux - else - { + else{ $node->getParent()->addChild($node); // spécifique page article diff --git a/src/controller/PageManagementController.php b/src/controller/PageManagementController.php index 2cc88a5..8efcb79 100644 --- a/src/controller/PageManagementController.php +++ b/src/controller/PageManagementController.php @@ -334,4 +334,21 @@ class PageManagementController } die; } + static public function changePaginationLimit(EntityManager $entityManager, array $json): void + { + if(isset($json['id']) && isset($json['pagination_limit'])){ + $director = new Director($entityManager); + $director->findNodeById($json['id']); + $old_limit = $director->getNode()->getNodeData()->getPaginationLimit() ?? 12; + $director->getNode()->getNodeData()->setPaginationLimit((int)$json['pagination_limit']); // attention conversion? + + $entityManager->flush(); + + echo json_encode(['success' => true, 'old_limit' => $old_limit, 'new_limit' => $json['pagination_limit']]); + } + else{ + echo json_encode(['success' => false]); + } + die; + } } \ No newline at end of file -- cgit v1.2.3