aboutsummaryrefslogtreecommitdiff
path: root/src/Model/Model.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Model/Model.php')
-rw-r--r--src/Model/Model.php316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/Model/Model.php b/src/Model/Model.php
new file mode 100644
index 0000000..fa8f764
--- /dev/null
+++ b/src/Model/Model.php
@@ -0,0 +1,316 @@
1<?php
2// src/Model/Model.php
3//
4// à l'occaz, faire des classes métiers: NodeModel = celle-ci
5// puis PageModel, puis éventuellement UserModel, EmailModel (le calendrier a déjà EventDTO)
6
7declare(strict_types=1);
8
9namespace App\Model;
10
11use Doctrine\ORM\EntityManager;
12use Doctrine\ORM\QueryBuilder;
13use Symfony\Component\HttpFoundation\Request;
14use App\Entity\Page;
15use App\Entity\Node;
16use App\Entity\Presentation;
17use App\Model\Menu;
18use App\Model\Path;
19
20class Model
21{
22 private EntityManager $entityManager;
23 static public Menu $menu; // pour NavBuilder
24 static public ?Path $page_path = null; // pour $current dans NavBuilder et pour BreadcrumbBuilder
25 private Page $page;
26 private ?Node $node;
27 private Node $article;
28
29 public function __construct(EntityManager $entityManager)
30 {
31 $this->entityManager = $entityManager;
32 $this->node = new Node; // instance mère "vide" ne possédant rien d'autre que des enfants
33 }
34
35 // à déplacer dans Path ou un truc comme ça?
36 // couper Model en deux classes NodeModel et PageModel?
37 public function makeMenuAndPaths(): void // lit la table "page"
38 {
39 self::$menu = new Menu($this->entityManager);
40 self::$page_path = new Path();
41 $this->page = self::$page_path->getLast();
42 }
43
44 public function getNode(): Node
45 {
46 return $this->node;
47 }
48 public function getArticleNode(): Node
49 {
50 return $this->article;
51 }
52
53 // affichage d'une page ordinaire
54 public function getWholePageData(Request $request): void // lit la table "node" + jointures
55 {
56 $id = CURRENT_PAGE === 'article' ? htmlspecialchars($request->query->get('id')) : '';
57
58 if($id === ''){ // page "normale"
59 // récupérer tous les noeuds sauf les articles
60 $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)";
61 $bulk_data = $this->entityManager
62 ->createQuery($dql)
63 ->setParameter('page', $this->page)
64 ->getResult();
65
66 foreach($bulk_data as $parent_block){
67 // groupes d'articles triés par bloc, permet de paginer par bloc
68 if(Presentation::hasPresentation($parent_block->getName())){ // = post_block ou news_block
69 $bulk_data = array_merge($bulk_data, $this->getNextArticles($parent_block, $request)[0]);
70 }
71
72 // emails
73 if($parent_block->getName() === 'show_emails'){ // show_emails = l'afficheur
74 $parent_block->getNodeData()->setEmails($this->getAllEmails());
75
76 // aller chercher les formulaires à la place (future MAJ?)
77 //$this->getFormsNodeData();
78 }
79 }
80 }
81 else{ // page "article"
82 $dql = 'SELECT n FROM App\Entity\Node n WHERE n.page = :page OR n.page IS null OR n.id_node = :id';
83 $bulk_data = $this->entityManager
84 ->createQuery($dql)
85 ->setParameter('page', $this->page)
86 ->setParameter('id', $id)
87 ->getResult();
88 }
89
90 $this->makeNodeTree($bulk_data);
91 }
92
93 // récupération d'articles
94 public function getNextArticles(Node $parent_block, Request $request): array
95 {
96 $qb = $this->entityManager->createQueryBuilder();
97 $qb->select('n')
98 ->from('App\Entity\Node', 'n')
99 ->where('n.parent = :parent')
100 ->setParameter('parent', $parent_block);
101
102 if($parent_block->getName() === 'post_block'){
103 $qb->orderBy('n.position');
104 }
105 elseif($parent_block->getName() === 'news_block'){
106 $qb->join('n.article', 'a');
107 if($parent_block->getNodeData()->getChronoOrder() ?? false){ // ordre antichrono par défaut
108 $qb->orderBy('a.date_time', 'ASC');
109 }
110 else{
111 $qb->orderBy('a.date_time', 'DESC');
112 }
113 }
114
115 // pagination
116 $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD
117 $this->paginateWithCursor($qb, $parent_block, $request->query->get('last_article'));
118 $result = $qb->getQuery()->getResult();
119
120 // il reste des articles à récupérer SI on vient d'en récupérer trop
121 // ET on gère le cas particulier de $limit <= 0
122 $truncated = false;
123 if(count($result) > $limit && $limit > 0){ // si nb résultat > limit > 0
124 $truncated = true;
125 array_pop($result); // compenser le $limit + 1 dans paginateWithCursor
126 }
127
128 return [$result, $truncated]; // besoin exceptionnel de retourner deux valeurs
129 }
130
131 private function paginateWithCursor(QueryBuilder $qb, Node $parent_block, ?string $last_article): void
132 {
133 //var_dump($last_article);
134 $limit = $parent_block->getNodeData()->getPaginationLimit(); // = 12 par défaut si = null en BDD
135
136 if($limit > 0){ // si 0 ou moins pas de pagination
137 // nombres de "pages" d'articles
138 $nb_pages = $this->getNumberOfPages($parent_block, $limit);
139 $parent_block->getNodeData()->setNumberOfPages($nb_pages > 1 ? $nb_pages : 1);
140
141 // adaptation de la requête
142 if($parent_block->getName() === 'post_block'){
143 $qb->andWhere('n.position > :last_position')
144 ->setParameter('last_position', empty($last_article) ? 0 : $last_article)
145 ->setMaxResults($limit + 1);
146 }
147 elseif($parent_block->getName() === 'news_block'){
148 $cursor_start = $parent_block->getNodeData()->getChronoOrder() ? '1970-01-01' : '9999-12-31';
149 $qb->andWhere($parent_block->getNodeData()->getChronoOrder() ? 'a.date_time > :date_time' : 'a.date_time < :date_time')
150 ->setParameter('date_time', empty($last_article) ? $cursor_start : $last_article)
151 ->setMaxResults($limit + 1);
152 }
153 }
154 }
155
156 // le Paginator de doctrine le fait aussi si on décidait de s'en servir
157 private function getNumberOfPages(Node $parent_block, int $limit): int
158 {
159 $dql = 'SELECT COUNT(n.id_node) FROM App\Entity\Node n WHERE n.parent = :parent';
160 $nb_articles = $this->entityManager
161 ->createQuery($dql)
162 ->setParameter('parent', $parent_block)
163 ->getSingleScalarResult();
164 return (int)ceil($nb_articles / $limit); // que PHP fasse une division non euclidienne (pas comme en C) nous arrange ici
165 }
166
167 private function makeNodeTree(array $bulk_data): void // $bulk_data = tableau de Node
168 {
169 // puis on les range
170 // (attention, risque de disfonctionnement si les noeuds de 1er niveau ne sont pas récupérés en 1er dans la BDD)
171 foreach($bulk_data as $node){
172 // premier niveau
173 if($node->getParent() == null){
174 $this->node->addChild($node);
175
176 // spécifique page article
177 if($node->getName() === 'main' && $this->page->getEndOfPath() == 'article'){
178 $main = $node;
179 }
180 }
181 // autres niveaux
182 else{
183 $node->getParent()->addChild($node);
184
185 // spécifique page article
186 if($this->page->getEndOfPath() == 'article'){
187 if($node->getName() === 'new'){
188 $new = $node;
189 }
190 }
191 }
192 }
193 if(isset($new)){
194 $main->setAdoptedChild($new);
195 }
196 }
197
198 // le basique
199 public function findNodeById(int $id): bool
200 {
201 $this->node = $this->entityManager->find('App\Entity\Node', $id);
202 return $this->node === null ? false : true;
203 }
204 public function findWhateverNode(string $field, string $value): bool
205 {
206 $queryBuilder = $this->entityManager->createQueryBuilder();
207 $queryBuilder
208 ->select('n')
209 ->from('App\Entity\Node', 'n')
210 ->where("n.$field = :value") // avec le querybuilder, ce truc sale reste sécurisé
211 ->setParameter('value', $value);
212 $result = $queryBuilder->getQuery()->getOneOrNullResult();
213
214 if($result === null){
215 return false;
216 }
217 else{
218 $this->node = $result;
219 return true;
220 }
221 }
222 public function getWhatever(string $class, string $field, string $value): array
223 {
224 // penser au entityManager "repository"
225 $queryBuilder = $this->entityManager->createQueryBuilder();
226 $queryBuilder
227 ->select('n')
228 ->from($class, 'n')
229 ->where("n.$field = :value")
230 ->setParameter('value', $value);
231 return $queryBuilder->getQuery()->getResult();
232 }
233
234 // récupération d'un article pour modification
235 public function makeArticleNode(string $id = '', bool $get_section = false): bool
236 {
237 if($get_section){
238 $dql = 'SELECT n, p FROM App\Entity\Node n LEFT JOIN n.parent p WHERE n.id_node = :id';
239 }
240 else{
241 $dql = 'SELECT n FROM App\Entity\Node n WHERE n.id_node = :id';
242 }
243 // n est l'article et p son $parent
244 $bulk_data = $this->entityManager
245 ->createQuery($dql)
246 ->setParameter('id', $id)
247 ->getResult();
248
249 if(count($bulk_data) === 0){
250 return false;
251 }
252
253 if($get_section){
254 $this->article = $bulk_data[0];
255 $this->findNodeById($bulk_data[0]->getParent()->getId());
256 $this->makeSectionNode();
257 }
258 else{
259 $this->article = $bulk_data[0];
260 }
261
262 return true;
263 }
264
265 // récupération des articles d'un bloc <section> à la création d'un article
266 public function makeSectionNode(): bool
267 {
268 $bulk_data = $this->entityManager
269 ->createQuery('SELECT n FROM App\Entity\Node n WHERE n.parent = :parent')
270 ->setParameter('parent', $this->node)
271 ->getResult();
272
273 foreach($bulk_data as $article){
274 $this->node->addChild($article); // pas de flush, on ne va pas écrire dans la BDD à chaque nouvelle page
275 }
276 return true;
277 }
278
279 public function findUniqueNodeByName(string $name): void // = unique en BDD, donc sans "page" associée
280 {
281 $bulk_data = $this->entityManager
282 ->createQuery('SELECT n FROM App\Entity\Node n WHERE n.name_node = :name')
283 ->setParameter('name', $name)
284 ->getResult();
285 $this->node = $bulk_data[0];
286 }
287
288 public function findItsChildren(): void
289 {
290 $bulk_data = $this->entityManager
291 ->createQuery('SELECT n FROM App\Entity\Node n WHERE n.parent = :parent AND n.page = :page')
292 ->setParameter('parent', $this->node)
293 ->setParameter('page', $this->page)
294 ->getResult();
295 foreach($bulk_data as $child){
296 $this->node->addChild($child);
297 }
298 }
299
300 private function getAllEmails(): array
301 {
302 $dql = 'SELECT e FROM App\Entity\Email e';
303 return $this->entityManager
304 ->createQuery($dql)
305 ->getResult();
306 }
307 /*private function getFormsNodeData(): array
308 {
309 $dql = 'SELECT fd FROM App\Entity\NodeData fd WHERE node.name_node = form';
310 return $this->entityManager
311 ->createQuery($dql)
312 //->setParameter('page', $this->page)
313 ->getResult();
314 }*/
315 //private function getEmailsBySender(string $sender): array
316}