These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\NodeBundle\Repository; |
||
4 | |||
5 | use Gedmo\Tree\Entity\Repository\NestedTreeRepository; |
||
6 | use Kunstmaan\AdminBundle\Entity\BaseUser; |
||
7 | use Kunstmaan\AdminBundle\Helper\Security\Acl\AclHelper; |
||
8 | use Kunstmaan\AdminBundle\Helper\Security\Acl\AclNativeHelper; |
||
9 | use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionDefinition; |
||
10 | use Kunstmaan\NodeBundle\Entity\HasNodeInterface; |
||
11 | use Kunstmaan\NodeBundle\Entity\Node; |
||
12 | use Kunstmaan\NodeBundle\Entity\NodeTranslation; |
||
13 | use Kunstmaan\NodeBundle\Entity\NodeVersion; |
||
14 | use Kunstmaan\NodeBundle\Helper\HiddenFromNavInterface; |
||
15 | use Kunstmaan\UtilitiesBundle\Helper\ClassLookup; |
||
16 | |||
17 | /** |
||
18 | * NodeRepository |
||
19 | */ |
||
20 | class NodeRepository extends NestedTreeRepository |
||
21 | { |
||
22 | /** |
||
23 | * @param string $lang The locale |
||
24 | * @param string $permission The permission (read, write, ...) |
||
25 | * @param AclHelper $aclHelper The acl helper |
||
26 | * @param bool $includeHiddenFromNav include the hiddenfromnav nodes |
||
27 | * or not |
||
28 | * |
||
29 | * @return Node[] |
||
30 | */ |
||
31 | public function getTopNodes( |
||
32 | $lang, |
||
33 | $permission, |
||
34 | AclHelper $aclHelper, |
||
35 | $includeHiddenFromNav = false |
||
36 | ) { |
||
37 | $result = $this->getChildNodes( |
||
38 | null, |
||
39 | $lang, |
||
40 | $permission, |
||
41 | $aclHelper, |
||
42 | $includeHiddenFromNav |
||
43 | ); |
||
44 | |||
45 | return $result; |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * @param int|null $parentId The parent node id |
||
50 | * @param string $lang The locale |
||
51 | * @param string $permission The permission (read, write, ...) |
||
52 | * @param AclHelper $aclHelper The acl helper |
||
53 | * @param bool $includeHiddenFromNav Include nodes hidden from |
||
54 | * navigation or not |
||
55 | * @param Node $rootNode Root node of the current tree |
||
56 | * |
||
57 | * @return Node[] |
||
58 | */ |
||
59 | public function getChildNodes( |
||
60 | $parentId, |
||
61 | $lang, |
||
62 | $permission, |
||
63 | AclHelper $aclHelper, |
||
64 | $includeHiddenFromNav = false, |
||
65 | $includeHiddenWithInternalName = false, |
||
66 | $rootNode = null |
||
67 | ) { |
||
68 | $qb = $this->createQueryBuilder('b') |
||
69 | ->select('b', 't', 'v') |
||
70 | ->leftJoin('b.nodeTranslations', 't', 'WITH', 't.lang = :lang') |
||
71 | ->leftJoin( |
||
72 | 't.publicNodeVersion', |
||
73 | 'v', |
||
74 | 'WITH', |
||
75 | 't.publicNodeVersion = v.id' |
||
76 | ) |
||
77 | ->where('b.deleted = 0') |
||
78 | ->setParameter('lang', $lang) |
||
79 | ->addOrderBy('t.weight', 'ASC') |
||
80 | ->addOrderBy('t.title', 'ASC'); |
||
81 | |||
82 | if (!$includeHiddenFromNav) { |
||
83 | if ($includeHiddenWithInternalName) { |
||
84 | $qb->andWhere( |
||
85 | '(b.hiddenFromNav != true OR b.internalName IS NOT NULL)' |
||
86 | ); |
||
87 | } else { |
||
88 | $qb->andWhere('b.hiddenFromNav != true'); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | View Code Duplication | if (is_null($parentId)) { |
|
93 | $qb->andWhere('b.parent is NULL'); |
||
94 | } elseif ($parentId !== false) { |
||
95 | $qb->andWhere('b.parent = :parent') |
||
96 | ->setParameter('parent', $parentId); |
||
97 | } |
||
98 | if ($rootNode) { |
||
99 | $qb->andWhere('b.lft >= :left') |
||
100 | ->andWhere('b.rgt <= :right') |
||
101 | ->setParameter('left', $rootNode->getLeft()) |
||
102 | ->setParameter('right', $rootNode->getRight()); |
||
103 | } |
||
104 | |||
105 | $query = $aclHelper->apply( |
||
106 | $qb, |
||
107 | new PermissionDefinition(array($permission)) |
||
108 | ); |
||
109 | |||
110 | return $query->getResult(); |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * @param HasNodeInterface $hasNode |
||
115 | * |
||
116 | * @return Node|null |
||
117 | */ |
||
118 | public function getNodeFor(HasNodeInterface $hasNode) |
||
119 | { |
||
120 | /* @var NodeVersion $nodeVersion */ |
||
121 | $nodeVersion = $this->getEntityManager()->getRepository( |
||
122 | 'KunstmaanNodeBundle:NodeVersion' |
||
123 | )->getNodeVersionFor( |
||
124 | $hasNode |
||
125 | ); |
||
126 | if (!is_null($nodeVersion)) { |
||
127 | /* @var NodeTranslation $nodeTranslation */ |
||
128 | $nodeTranslation = $nodeVersion->getNodeTranslation(); |
||
129 | if (!is_null($nodeTranslation)) { |
||
130 | return $nodeTranslation->getNode(); |
||
131 | } |
||
132 | } |
||
133 | |||
134 | return null; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @param int $id The id |
||
139 | * @param string $entityName The class name |
||
140 | * |
||
141 | * @return Node|null |
||
142 | */ |
||
143 | public function getNodeForIdAndEntityname($id, $entityName) |
||
144 | { |
||
145 | /* @var NodeVersion $nodeVersion */ |
||
146 | $nodeVersion = $this->getEntityManager()->getRepository( |
||
147 | 'KunstmaanNodeBundle:NodeVersion' |
||
148 | )->findOneBy( |
||
149 | array('refId' => $id, 'refEntityName' => $entityName) |
||
150 | ); |
||
151 | if ($nodeVersion) { |
||
152 | return $nodeVersion->getNodeTranslation()->getNode(); |
||
153 | } |
||
154 | |||
155 | return null; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * @param Node $parentNode The parent node (may be null) |
||
160 | * @param string $slug The slug |
||
161 | * |
||
162 | * @return Node|null |
||
163 | */ |
||
164 | public function getNodeForSlug(Node $parentNode, $slug) |
||
165 | { |
||
166 | $slugParts = explode('/', $slug); |
||
167 | $result = null; |
||
168 | foreach ($slugParts as $slugPart) { |
||
169 | if ($parentNode) { |
||
170 | if ($r = $this->findOneBy( |
||
171 | array( |
||
172 | 'slug' => $slugPart, |
||
173 | 'parent.parent' => $parentNode->getId(), |
||
174 | ) |
||
175 | ) |
||
176 | ) { |
||
177 | $result = $r; |
||
178 | } |
||
179 | } else { |
||
180 | if ($r = $this->findOneBy(array('slug' => $slugPart))) { |
||
181 | $result = $r; |
||
182 | } |
||
183 | } |
||
184 | } |
||
185 | |||
186 | return $result; |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * @param HasNodeInterface $hasNode The object to link to |
||
191 | * @param string $lang The locale |
||
192 | * @param BaseUser $owner The user |
||
193 | * @param string $internalName The internal name (may be null) |
||
194 | * |
||
195 | * @throws \InvalidArgumentException |
||
196 | * |
||
197 | * @return Node |
||
198 | */ |
||
199 | public function createNodeFor( |
||
200 | HasNodeInterface $hasNode, |
||
201 | $lang, |
||
202 | BaseUser $owner, |
||
203 | $internalName = null |
||
204 | ) { |
||
205 | $em = $this->getEntityManager(); |
||
206 | $node = new Node(); |
||
207 | $node->setRef($hasNode); |
||
208 | if (!$hasNode->getId() > 0) { |
||
209 | throw new \InvalidArgumentException( |
||
210 | 'the entity of class '. |
||
211 | $node->getRefEntityName( |
||
212 | ).' has no id, maybe you forgot to flush first' |
||
213 | ); |
||
214 | } |
||
215 | $node->setDeleted(false); |
||
216 | $node->setInternalName($internalName); |
||
217 | $parent = $hasNode->getParent(); |
||
218 | if ($parent) { |
||
219 | /* @var NodeVersion $parentNodeVersion */ |
||
220 | $parentNodeVersion = $em->getRepository( |
||
221 | 'KunstmaanNodeBundle:NodeVersion' |
||
222 | )->findOneBy( |
||
223 | array( |
||
224 | 'refId' => $parent->getId(), |
||
225 | 'refEntityName' => ClassLookup::getClass($parent), |
||
226 | ) |
||
227 | ); |
||
228 | if ($parentNodeVersion) { |
||
229 | $node->setParent( |
||
230 | $parentNodeVersion->getNodeTranslation()->getNode() |
||
231 | ); |
||
232 | } |
||
233 | } |
||
234 | if ($hasNode instanceof HiddenFromNavInterface) { |
||
235 | $node->setHiddenFromNav($hasNode->isHiddenFromNav()); |
||
236 | } |
||
237 | $em->persist($node); |
||
238 | $em->flush(); |
||
239 | $em->refresh($node); |
||
240 | $em->getRepository('KunstmaanNodeBundle:NodeTranslation') |
||
241 | ->createNodeTranslationFor( |
||
242 | $hasNode, |
||
243 | $lang, |
||
244 | $node, |
||
245 | $owner |
||
246 | ); |
||
247 | |||
248 | return $node; |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Get all the information needed to build a menu tree with one query. |
||
253 | * We only fetch the fields we need, instead of fetching full objects to |
||
254 | * limit the memory usage. |
||
255 | * |
||
256 | * @param string $lang The locale |
||
257 | * @param string $permission The permission (read, |
||
258 | * write, ...) |
||
259 | * @param AclNativeHelper $aclNativeHelper The acl helper |
||
260 | * @param bool $includeHiddenFromNav Include nodes hidden from |
||
261 | * navigation or not |
||
262 | * @param Node $rootNode The root node of the |
||
263 | * current site |
||
264 | * |
||
265 | * @return array |
||
266 | */ |
||
267 | public function getAllMenuNodes( |
||
268 | $lang, |
||
269 | $permission, |
||
270 | AclNativeHelper $aclNativeHelper, |
||
271 | $includeHiddenFromNav = false, |
||
272 | Node $rootNode = null |
||
273 | ) { |
||
274 | $connection = $this->_em->getConnection(); |
||
275 | $qb = $connection->createQueryBuilder(); |
||
276 | $databasePlatformName = $connection->getDatabasePlatform()->getName(); |
||
277 | $createIfStatement = function ( |
||
278 | $expression, |
||
279 | $trueValue, |
||
280 | $falseValue |
||
281 | ) use ($databasePlatformName) { |
||
282 | switch ($databasePlatformName) { |
||
283 | case 'sqlite': |
||
284 | $statement = 'CASE WHEN %s THEN %s ELSE %s END'; |
||
285 | |||
286 | break; |
||
287 | |||
288 | default: |
||
289 | $statement = 'IF(%s, %s, %s)'; |
||
290 | } |
||
291 | |||
292 | return sprintf($statement, $expression, $trueValue, $falseValue); |
||
293 | }; |
||
294 | |||
295 | $sql = <<<SQL |
||
296 | n.id, n.parent_id AS parent, t.url, t.id AS nt_id, |
||
297 | {$createIfStatement('t.weight IS NULL', 'v.weight', 't.weight')} AS weight, |
||
298 | {$createIfStatement('t.title IS NULL', 'v.title', 't.title')} AS title, |
||
299 | {$createIfStatement('t.online IS NULL', '0', 't.online')} AS online, |
||
300 | n.hidden_from_nav AS hidden, |
||
301 | n.ref_entity_name AS ref_entity_name |
||
302 | SQL; |
||
303 | |||
304 | $qb->select($sql) |
||
305 | ->from('kuma_nodes', 'n') |
||
306 | ->leftJoin( |
||
307 | 'n', |
||
308 | 'kuma_node_translations', |
||
309 | 't', |
||
310 | '(t.node_id = n.id AND t.lang = :lang)' |
||
311 | ) |
||
312 | ->leftJoin( |
||
313 | 'n', |
||
314 | 'kuma_node_translations', |
||
315 | 'v', |
||
316 | '(v.node_id = n.id AND v.lang <> :lang)' |
||
317 | ) |
||
318 | ->where('n.deleted = 0') |
||
319 | ->addGroupBy('n.id') |
||
320 | ->addOrderBy('t.weight', 'ASC') |
||
321 | ->addOrderBy('t.title', 'ASC'); |
||
322 | |||
323 | if (!$includeHiddenFromNav) { |
||
324 | $qb->andWhere('n.hidden_from_nav <> 0'); |
||
325 | } |
||
326 | |||
327 | if (!is_null($rootNode)) { |
||
328 | $qb->andWhere('n.lft >= :left') |
||
329 | ->andWhere('n.rgt <= :right'); |
||
330 | } |
||
331 | |||
332 | $permissionDef = new PermissionDefinition(array($permission)); |
||
333 | $permissionDef->setEntity('Kunstmaan\NodeBundle\Entity\Node'); |
||
334 | $permissionDef->setAlias('n'); |
||
335 | $qb = $aclNativeHelper->apply($qb, $permissionDef); |
||
336 | |||
337 | $stmt = $this->_em->getConnection()->prepare($qb->getSQL()); |
||
338 | $stmt->bindValue(':lang', $lang); |
||
339 | if (!is_null($rootNode)) { |
||
340 | $stmt->bindValue(':left', $rootNode->getLeft()); |
||
341 | $stmt->bindValue(':right', $rootNode->getRight()); |
||
342 | } |
||
343 | $stmt->execute(); |
||
344 | |||
345 | return $stmt->fetchAll(); |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Get all parents of a given node. We can go multiple levels up. |
||
350 | * |
||
351 | * @param Node $node |
||
352 | * @param string $lang |
||
353 | * |
||
354 | * @return Node[] |
||
355 | */ |
||
356 | View Code Duplication | public function getAllParents(Node $node = null, $lang = null) |
|
357 | { |
||
358 | if (is_null($node)) { |
||
359 | return array(); |
||
360 | } |
||
361 | |||
362 | $qb = $this->createQueryBuilder('node'); |
||
363 | |||
364 | // Directly hydrate the nodeTranslation and nodeVersion |
||
365 | $qb->select('node', 't', 'v') |
||
366 | ->innerJoin('node.nodeTranslations', 't') |
||
367 | ->leftJoin( |
||
368 | 't.publicNodeVersion', |
||
369 | 'v', |
||
370 | 'WITH', |
||
371 | 't.publicNodeVersion = v.id' |
||
372 | ) |
||
373 | ->where('node.deleted = 0'); |
||
374 | |||
375 | if ($lang) { |
||
376 | $qb->andWhere('t.lang = :lang') |
||
377 | ->setParameter('lang', $lang); |
||
378 | } |
||
379 | |||
380 | $qb->andWhere( |
||
381 | $qb->expr()->andX( |
||
382 | $qb->expr()->lte('node.lft', $node->getLeft()), |
||
383 | $qb->expr()->gte('node.rgt', $node->getRight()) |
||
384 | ) |
||
385 | ); |
||
386 | |||
387 | $qb->addOrderBy('node.lft', 'ASC'); |
||
388 | |||
389 | return $qb->getQuery()->getResult(); |
||
390 | } |
||
391 | |||
392 | /** |
||
393 | * Get the root node of a given node. |
||
394 | * |
||
395 | * @param Node $node |
||
396 | * @param string $lang |
||
397 | * |
||
398 | * @return Node |
||
399 | */ |
||
400 | View Code Duplication | public function getRootNodeFor(Node $node = null, $lang = null) |
|
401 | { |
||
402 | if (is_null($node)) { |
||
403 | return null; |
||
404 | } |
||
405 | |||
406 | $qb = $this->createQueryBuilder('node'); |
||
407 | |||
408 | // Directly hydrate the nodeTranslation and nodeVersion |
||
409 | $qb->select('node', 't', 'v') |
||
410 | ->innerJoin('node.nodeTranslations', 't') |
||
411 | ->leftJoin( |
||
412 | 't.publicNodeVersion', |
||
413 | 'v', |
||
414 | 'WITH', |
||
415 | 't.publicNodeVersion = v.id' |
||
416 | ) |
||
417 | ->where('node.deleted = 0') |
||
418 | ->andWhere('node.parent IS NULL'); |
||
419 | |||
420 | if ($lang) { |
||
421 | $qb->andWhere('t.lang = :lang') |
||
422 | ->setParameter('lang', $lang); |
||
423 | } |
||
424 | |||
425 | $qb->andWhere( |
||
426 | $qb->expr()->andX( |
||
427 | $qb->expr()->lte('node.lft', $node->getLeft()), |
||
428 | $qb->expr()->gte('node.rgt', $node->getRight()) |
||
429 | ) |
||
430 | ); |
||
431 | |||
432 | return $qb->getQuery()->getOneOrNullResult(); |
||
433 | } |
||
434 | |||
435 | /** |
||
436 | * @return Node[] |
||
437 | */ |
||
438 | public function getAllTopNodes() |
||
439 | { |
||
440 | $qb = $this->createQueryBuilder('b') |
||
441 | ->select('b', 't', 'v') |
||
442 | ->leftJoin('b.nodeTranslations', 't') |
||
443 | ->leftJoin( |
||
444 | 't.publicNodeVersion', |
||
445 | 'v', |
||
446 | 'WITH', |
||
447 | 't.publicNodeVersion = v.id' |
||
448 | ) |
||
449 | ->where('b.deleted = 0') |
||
450 | ->andWhere('b.parent IS NULL'); |
||
451 | |||
452 | $result = $qb->getQuery()->getResult(); |
||
453 | |||
454 | return $result; |
||
455 | } |
||
456 | |||
457 | /** |
||
458 | * Get an array of Nodes based on the internal name. |
||
459 | * |
||
460 | * @param string $internalName The internal name of the node |
||
461 | * @param string $lang The locale |
||
462 | * @param int|null|bool $parentId The parent id |
||
463 | * @param bool $includeOffline Include offline nodes |
||
464 | * |
||
465 | * @return Node[] |
||
466 | */ |
||
467 | public function getNodesByInternalName( |
||
468 | $internalName, |
||
469 | $lang, |
||
470 | $parentId = false, |
||
471 | $includeOffline = false |
||
472 | ) { |
||
473 | $qb = $this->createQueryBuilder('n') |
||
474 | ->select('n', 't', 'v') |
||
475 | ->innerJoin('n.nodeTranslations', 't') |
||
476 | ->leftJoin( |
||
477 | 't.publicNodeVersion', |
||
478 | 'v', |
||
479 | 'WITH', |
||
480 | 't.publicNodeVersion = v.id' |
||
481 | ) |
||
482 | ->where('n.deleted = 0') |
||
483 | ->andWhere('n.internalName = :internalName') |
||
484 | ->setParameter('internalName', $internalName) |
||
485 | ->andWhere('t.lang = :lang') |
||
486 | ->setParameter('lang', $lang) |
||
487 | ->addOrderBy('t.weight', 'ASC') |
||
488 | ->addOrderBy('t.title', 'ASC'); |
||
489 | |||
490 | if (!$includeOffline) { |
||
491 | $qb->andWhere('t.online = true'); |
||
492 | } |
||
493 | |||
494 | View Code Duplication | if (is_null($parentId)) { |
|
495 | $qb->andWhere('n.parent is NULL'); |
||
496 | } elseif ($parentId === false) { |
||
0 ignored issues
–
show
|
|||
497 | // Do nothing |
||
498 | } else { |
||
499 | $qb->andWhere('n.parent = :parent') |
||
500 | ->setParameter('parent', $parentId); |
||
501 | } |
||
502 | |||
503 | $query = $qb->getQuery(); |
||
504 | |||
505 | return $query->getResult(); |
||
506 | } |
||
507 | |||
508 | /** |
||
509 | * Get a single node by internal name. |
||
510 | * |
||
511 | * @param string $internalName The internal name of the node |
||
512 | * |
||
513 | * @return Node |
||
514 | */ |
||
515 | public function getNodeByInternalName($internalName) |
||
516 | { |
||
517 | $qb = $this->createQueryBuilder('n') |
||
518 | ->select('n') |
||
519 | ->where('n.deleted = 0') |
||
520 | ->andWhere('n.internalName = :internalName') |
||
521 | ->setParameter('internalName', $internalName); |
||
522 | |||
523 | return $qb->getQuery()->getOneOrNullResult(); |
||
524 | } |
||
525 | |||
526 | /** |
||
527 | * Finds all different page classes currently registered as nodes |
||
528 | * |
||
529 | * @return string[] |
||
530 | */ |
||
531 | public function findAllDistinctPageClasses() |
||
532 | { |
||
533 | $qb = $this->createQueryBuilder('n') |
||
534 | ->select('n.refEntityName') |
||
535 | ->where('n.deleted = 0') |
||
536 | ->distinct(true); |
||
537 | |||
538 | return $qb->getQuery()->getArrayResult(); |
||
539 | } |
||
540 | } |
||
541 |
This check looks for the bodies of
elseif
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
elseif
bodies can be removed. If you have an empty elseif but statements in theelse
branch, consider inverting the condition.