NodeMenu   F
last analyzed

Complexity

Total Complexity 87

Size/Duplication

Total Lines 679
Duplicated Lines 9.57 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 87
lcom 2
cbo 7
dl 65
loc 679
ccs 0
cts 256
cp 0
rs 1.921
c 0
b 0
f 0

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A setLocale() 0 4 1
A setCurrentNode() 0 4 1
A setPermission() 0 8 2
A setIncludeOffline() 0 4 1
A setIncludeHiddenFromNav() 0 8 2
B init() 0 40 5
A getTopNodes() 9 26 5
B getChildren() 23 37 6
A getTopNodeMenuItems() 14 22 3
A getBreadCrumb() 0 33 4
A getCurrent() 10 10 2
A getActiveForDepth() 9 9 2
A getSiblings() 0 17 4
A getPreviousSibling() 0 16 5
A getNextSibling() 0 19 5
A getParent() 0 13 3
A getNodeBySlug() 0 5 1
D getNodeByInternalName() 0 88 19
A getRootNodeMenuItem() 0 22 3
A isIncludeOffline() 0 4 1
A getPermission() 0 4 1
A getUser() 0 4 1
A getEntityManager() 0 4 1
A getTokenStorage() 0 4 1
A getAclHelper() 0 4 1
A getLocale() 0 4 1
A isIncludeHiddenFromNav() 0 4 1
A getActive() 0 11 3
A isInitialized() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like NodeMenu often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use NodeMenu, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Kunstmaan\NodeBundle\Helper;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Kunstmaan\AdminBundle\Helper\DomainConfigurationInterface;
7
use Kunstmaan\AdminBundle\Helper\Security\Acl\AclHelper;
8
use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionMap;
9
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
10
use Kunstmaan\NodeBundle\Entity\Node;
11
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
12
use Kunstmaan\NodeBundle\Repository\NodeRepository;
13
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
14
15
class NodeMenu
16
{
17
    /**
18
     * @var EntityManagerInterface
19
     */
20
    private $em;
21
22
    /**
23
     * @var TokenStorageInterface
24
     */
25
    private $tokenStorage;
26
27
    /**
28
     * @var AclHelper
29
     */
30
    private $aclHelper;
31
32
    /**
33
     * @var string
34
     */
35
    private $locale;
36
37
    /**
38
     * @var Node
39
     */
40
    private $currentNode;
41
42
    /**
43
     * @var string
44
     */
45
    private $permission = PermissionMap::PERMISSION_VIEW;
46
47
    /**
48
     * @var bool
49
     */
50
    private $includeOffline = false;
51
52
    /**
53
     * @var bool
54
     */
55
    private $includeHiddenFromNav = false;
56
57
    /**
58
     * @var NodeMenuItem[]
59
     */
60
    private $topNodeMenuItems;
61
62
    /**
63
     * @var NodeMenuItem[]
64
     */
65
    private $breadCrumb;
66
67
    /**
68
     * @var Node[]
69
     */
70
    private $allNodes = array();
71
72
    /**
73
     * @var Node[]
74
     */
75
    private $childNodes = array();
76
77
    /**
78
     * @var Node[]
79
     */
80
    private $nodesByInternalName = array();
81
82
    /**
83
     * @var bool
84
     */
85
    private $initialized = false;
86
87
    /**
88
     * @var NodeMenuItem
89
     */
90
    private $rootNodeMenuItem;
91
92
    /**
93
     * @var DomainConfigurationInterface
94
     */
95
    private $domainConfiguration;
96
97
    /**
98
     * @param EntityManagerInterface       $em                  The entity manager
99
     * @param TokenStorageInterface        $tokenStorage        The security token storage
100
     * @param AclHelper                    $aclHelper           The ACL helper pages
101
     * @param DomainConfigurationInterface $domainConfiguration The current domain configuration
102
     */
103
    public function __construct(
104
        EntityManagerInterface $em,
105
        TokenStorageInterface $tokenStorage,
106
        AclHelper $aclHelper,
107
        DomainConfigurationInterface $domainConfiguration
108
    ) {
109
        $this->em = $em;
110
        $this->tokenStorage = $tokenStorage;
111
        $this->aclHelper = $aclHelper;
112
        $this->domainConfiguration = $domainConfiguration;
113
    }
114
115
    /**
116
     * @param string $locale
117
     */
118
    public function setLocale($locale)
119
    {
120
        $this->locale = $locale;
121
    }
122
123
    /**
124
     * @param Node $currentNode
0 ignored issues
show
Documentation introduced by Wim Vandersmissen
Should the type for parameter $currentNode not be null|Node?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
125
     */
126
    public function setCurrentNode(Node $currentNode = null)
127
    {
128
        $this->currentNode = $currentNode;
129
    }
130
131
    /**
132
     * @param string $permission
133
     */
134
    public function setPermission($permission)
135
    {
136
        if ($this->permission !== $permission) {
137
            // For now reset initialized flag when cached data has to be reset ...
138
            $this->initialized = false;
139
        }
140
        $this->permission = $permission;
141
    }
142
143
    /**
144
     * @param bool $includeOffline
145
     */
146
    public function setIncludeOffline($includeOffline)
147
    {
148
        $this->includeOffline = $includeOffline;
149
    }
150
151
    /**
152
     * @param bool $includeHiddenFromNav
153
     */
154
    public function setIncludeHiddenFromNav($includeHiddenFromNav)
155
    {
156
        if ($this->includeHiddenFromNav !== $includeHiddenFromNav) {
157
            // For now reset initialized flag when cached data has to be reset ...
158
            $this->initialized = false;
159
        }
160
        $this->includeHiddenFromNav = $includeHiddenFromNav;
161
    }
162
163
    /**
164
     * This method initializes the nodemenu only once, the method may be
165
     * executed multiple times
166
     */
167
    private function init()
168
    {
169
        if ($this->initialized) {
170
            return;
171
        }
172
173
        $this->allNodes = array();
174
        $this->breadCrumb = null;
0 ignored issues
show
Documentation Bug introduced by Wim Vandersmissen
It seems like null of type null is incompatible with the declared type array<integer,object<Kun...e\Helper\NodeMenuItem>> of property $breadCrumb.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
175
        $this->childNodes = array();
176
        $this->topNodeMenuItems = null;
0 ignored issues
show
Documentation Bug introduced by Wim Vandersmissen
It seems like null of type null is incompatible with the declared type array<integer,object<Kun...e\Helper\NodeMenuItem>> of property $topNodeMenuItems.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
177
        $this->nodesByInternalName = array();
178
179
        /* @var NodeRepository $repo */
180
        $repo = $this->em->getRepository('KunstmaanNodeBundle:Node');
181
182
        // Get all possible menu items in one query (also fetch offline nodes)
183
        $nodes = $repo->getChildNodes(
184
            false,
0 ignored issues
show
Documentation introduced by Wim Vandersmissen
false is of type boolean, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
185
            $this->locale,
186
            $this->permission,
187
            $this->aclHelper,
188
            $this->includeHiddenFromNav,
189
            true,
190
            $this->domainConfiguration->getRootNode()
191
        );
192
        foreach ($nodes as $node) {
193
            $this->allNodes[$node->getId()] = $node;
194
195
            if ($node->getParent()) {
196
                $this->childNodes[$node->getParent()->getId()][] = $node;
197
            } else {
198
                $this->childNodes[0][] = $node;
199
            }
200
            $internalName = $node->getInternalName();
201
            if ($internalName) {
202
                $this->nodesByInternalName[$internalName][] = $node;
203
            }
204
        }
205
        $this->initialized = true;
206
    }
207
208
    /**
209
     * @return NodeMenuItem[]
210
     */
211
    public function getTopNodes()
212
    {
213
        $this->init();
214
        if (!\is_array($this->topNodeMenuItems)) {
215
            $this->topNodeMenuItems = array();
216
217
            // To be backwards compatible we need to create the top node MenuItems
218
            if (\array_key_exists(0, $this->childNodes)) {
219
                $topNodeMenuItems = $this->getTopNodeMenuItems();
220
221
                $includeHiddenFromNav = $this->includeHiddenFromNav;
222
                $this->topNodeMenuItems = array_filter(
223
                    $topNodeMenuItems,
224 View Code Duplication
                    function (NodeMenuItem $entry) use ($includeHiddenFromNav) {
0 ignored issues
show
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
225
                        if ($entry->getNode()->isHiddenFromNav() && !$includeHiddenFromNav) {
226
                            return false;
227
                        }
228
229
                        return true;
230
                    }
231
                );
232
            }
233
        }
234
235
        return $this->topNodeMenuItems;
236
    }
237
238
    /**
239
     * @return NodeMenuItem[]
240
     */
241
    public function getBreadCrumb()
242
    {
243
        $this->init();
244
        if (!\is_array($this->breadCrumb)) {
245
            $this->breadCrumb = array();
246
247
            /* @var NodeRepository $repo */
248
            $repo = $this->em->getRepository('KunstmaanNodeBundle:Node');
249
250
            // Generate breadcrumb MenuItems - fetch *all* languages so you can link translations if needed
251
            $parentNodes = $repo->getAllParents($this->currentNode);
252
            $parentNodeMenuItem = null;
253
            /* @var Node $parentNode */
254
            foreach ($parentNodes as $parentNode) {
255
                $nodeTranslation = $parentNode->getNodeTranslation(
256
                    $this->locale,
257
                    $this->includeOffline
258
                );
259
                if (!\is_null($nodeTranslation)) {
260
                    $nodeMenuItem = new NodeMenuItem(
261
                        $parentNode,
262
                        $nodeTranslation,
263
                        $parentNodeMenuItem,
264
                        $this
265
                    );
266
                    $this->breadCrumb[] = $nodeMenuItem;
267
                    $parentNodeMenuItem = $nodeMenuItem;
268
                }
269
            }
270
        }
271
272
        return $this->breadCrumb;
273
    }
274
275
    /**
276
     * @return NodeMenuItem|null
277
     */
278 View Code Duplication
    public function getCurrent()
0 ignored issues
show
Duplication introduced by Kris Pypen
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
    {
280
        $this->init();
281
        $breadCrumb = $this->getBreadCrumb();
282
        if (\count($breadCrumb) > 0) {
283
            return $breadCrumb[\count($breadCrumb) - 1];
284
        }
285
286
        return null;
287
    }
288
289
    /**
290
     * @param int $depth
291
     *
292
     * @return NodeMenuItem|null
293
     */
294 View Code Duplication
    public function getActiveForDepth($depth)
0 ignored issues
show
Duplication introduced by Kris Pypen
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
    {
296
        $breadCrumb = $this->getBreadCrumb();
297
        if (\count($breadCrumb) >= $depth) {
298
            return $breadCrumb[$depth - 1];
299
        }
300
301
        return null;
302
    }
303
304
    /**
305
     * @param Node $node
306
     * @param bool $includeHiddenFromNav
307
     *
308
     * @return NodeMenuItem[]
309
     */
310
    public function getChildren(Node $node, $includeHiddenFromNav = true)
311
    {
312
        $this->init();
313
        $children = array();
314
315
        if (\array_key_exists($node->getId(), $this->childNodes)) {
316
            $nodes = $this->childNodes[$node->getId()];
317
            /* @var Node $childNode */
318 View Code Duplication
            foreach ($nodes as $childNode) {
0 ignored issues
show
Bug introduced by Wim Vandersmissen
The expression $nodes of type object<Kunstmaan\NodeBundle\Entity\Node> is not traversable.
Loading history...
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
319
                $nodeTranslation = $childNode->getNodeTranslation(
320
                    $this->locale,
321
                    $this->includeOffline
322
                );
323
                if (!\is_null($nodeTranslation)) {
324
                    $children[] = new NodeMenuItem(
325
                        $childNode,
326
                        $nodeTranslation,
327
                        false,
328
                        $this
329
                    );
330
                }
331
            }
332
333
            $children = array_filter(
334
                $children,
335 View Code Duplication
                function (NodeMenuItem $entry) use ($includeHiddenFromNav) {
0 ignored issues
show
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
336
                    if ($entry->getNode()->isHiddenFromNav() && !$includeHiddenFromNav) {
337
                        return false;
338
                    }
339
340
                    return true;
341
                }
342
            );
343
        }
344
345
        return $children;
346
    }
347
348
    /**
349
     * @param \Kunstmaan\NodeBundle\Entity\Node $node
350
     * @param bool                              $includeHiddenFromNav
351
     *
352
     * @return array|\Kunstmaan\NodeBundle\Helper\NodeMenuItem[]
353
     */
354
    public function getSiblings(Node $node, $includeHiddenFromNav = true)
355
    {
356
        $this->init();
357
        $siblings = array();
358
359
        if (false !== $parent = $this->getParent($node)) {
360
            $siblings = $this->getChildren($parent, $includeHiddenFromNav);
361
362
            foreach ($siblings as $index => $child) {
363
                if ($child === $node) {
364
                    unset($siblings[$index]);
365
                }
366
            }
367
        }
368
369
        return $siblings;
370
    }
371
372
    /**
373
     * @param \Kunstmaan\NodeBundle\Entity\Node $node
374
     * @param bool                              $includeHiddenFromNav
375
     *
376
     * @return bool|\Kunstmaan\NodeBundle\Helper\NodeMenuItem
0 ignored issues
show
Documentation introduced by blair
Consider making the return type a bit more specific; maybe use NodeMenuItem|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
377
     */
378
    public function getPreviousSibling(Node $node, $includeHiddenFromNav = true)
379
    {
380
        $this->init();
381
382
        if (false !== $parent = $this->getParent($node)) {
383
            $siblings = $this->getChildren($parent, $includeHiddenFromNav);
384
385
            foreach ($siblings as $index => $child) {
386
                if ($child->getNode() === $node && ($index - 1 >= 0)) {
387
                    return $siblings[$index - 1];
388
                }
389
            }
390
        }
391
392
        return false;
393
    }
394
395
    /**
396
     * @param \Kunstmaan\NodeBundle\Entity\Node $node
397
     * @param bool                              $includeHiddenFromNav
398
     *
399
     * @return bool|\Kunstmaan\NodeBundle\Helper\NodeMenuItem
0 ignored issues
show
Documentation introduced by blair
Consider making the return type a bit more specific; maybe use NodeMenuItem|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
400
     */
401
    public function getNextSibling(Node $node, $includeHiddenFromNav = true)
402
    {
403
        $this->init();
404
405
        if (false !== $parent = $this->getParent($node)) {
406
            $siblings = $this->getChildren($parent, $includeHiddenFromNav);
407
408
            foreach ($siblings as $index => $child) {
409
                if ($child->getNode() === $node && (($index + 1) < \count(
410
                            $siblings
411
                        ))
412
                ) {
413
                    return $siblings[$index + 1];
414
                }
415
            }
416
        }
417
418
        return false;
419
    }
420
421
    /**
422
     * @param Node $node
423
     *
424
     * @return NodeMenuItem
0 ignored issues
show
Documentation introduced by Kristof Jochmans
Should the return type not be Node|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
425
     */
426
    public function getParent(Node $node)
427
    {
428
        $this->init();
429
        if ($node->getParent() && \array_key_exists(
430
                $node->getParent()->getId(),
431
                $this->allNodes
432
            )
433
        ) {
434
            return $this->allNodes[$node->getParent()->getId()];
435
        }
436
437
        return false;
438
    }
439
440
    /**
441
     * @param NodeTranslation $parentNode The parent node
442
     * @param string          $slug       The slug
443
     *
444
     * @return NodeTranslation
445
     */
446
    public function getNodeBySlug(NodeTranslation $parentNode, $slug)
447
    {
448
        return $this->em->getRepository('KunstmaanNodeBundle:NodeTranslation')
449
            ->getNodeTranslationForSlug($slug, $parentNode);
450
    }
451
452
    /**
453
     * @param string                                        $internalName   The
454
     *                                                                      internal
455
     *                                                                      name
456
     * @param NodeTranslation|NodeMenuItem|HasNodeInterface $parent         The
0 ignored issues
show
Documentation introduced by Wim Vandersmissen
Should the type for parameter $parent not be NodeTranslation|NodeMenuItem|HasNodeInterface|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
457
     *                                                                      parent
458
     * @param bool                                          $includeOffline
0 ignored issues
show
Documentation introduced by Kenny Debrauwer
Should the type for parameter $includeOffline not be boolean|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
459
     *
460
     * @return NodeMenuItem|null
461
     */
462
    public function getNodeByInternalName(
463
        $internalName,
464
        $parent = null,
465
        $includeOffline = null
466
    ) {
467
        $this->init();
468
        $resultNode = null;
469
470
        if (\is_null($includeOffline)) {
471
            $includeOffline = $this->includeOffline;
472
        }
473
474
        if (\array_key_exists($internalName, $this->nodesByInternalName)) {
475
            $nodes = $this->nodesByInternalName[$internalName];
476
            $nodes = array_filter(
477
                $nodes,
478
                function (Node $entry) use ($includeOffline) {
479
                    if ($entry->isDeleted() && !$includeOffline) {
480
                        return false;
481
                    }
482
483
                    return true;
484
                }
485
            );
486
487
            if (!\is_null($parent)) {
488
                /** @var Node $parentNode */
489
                if ($parent instanceof NodeTranslation) {
490
                    $parentNode = $parent->getNode();
491
                } elseif ($parent instanceof NodeMenuItem) {
492
                    $parentNode = $parent->getNode();
493
                } elseif ($parent instanceof HasNodeInterface) {
494
                    $repo = $this->em->getRepository(
495
                        'KunstmaanNodeBundle:Node'
496
                    );
497
                    $parentNode = $repo->getNodeFor($parent);
498
                }
499
500
                // Look for a node with the same parent id
501
                /** @var Node $node */
502
                foreach ($nodes as $node) {
503
                    if ($node->getParent()->getId() == $parentNode->getId()) {
0 ignored issues
show
Bug introduced by Kristof Jochmans
The variable $parentNode does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
504
                        $resultNode = $node;
505
506
                        break;
507
                    }
508
                }
509
510
                // Look for a node that has an ancestor with the same parent id
511
                if (\is_null($resultNode)) {
512
                    /* @var Node $n */
513
                    foreach ($nodes as $node) {
514
                        $tempNode = $node;
515
                        while (\is_null($resultNode) && !\is_null(
516
                                $tempNode->getParent()
517
                            )) {
518
                            $tempParent = $tempNode->getParent();
519
                            if ($tempParent->getId() == $parentNode->getId()) {
520
                                $resultNode = $node;
521
522
                                break;
523
                            }
524
                            $tempNode = $tempParent;
525
                        }
526
                    }
527
                }
528
            } elseif (\count($nodes) > 0) {
529
                $resultNode = $nodes[0];
530
            }
531
        }
532
533
        if ($resultNode) {
534
            $nodeTranslation = $resultNode->getNodeTranslation(
535
                $this->locale,
536
                $includeOffline
537
            );
538
            if (!\is_null($nodeTranslation)) {
539
                return new NodeMenuItem(
540
                    $resultNode,
541
                    $nodeTranslation,
542
                    false,
543
                    $this
544
                );
545
            }
546
        }
547
548
        return null;
549
    }
550
551
    /**
552
     * Returns the current root node menu item
553
     */
554
    public function getRootNodeMenuItem()
555
    {
556
        if (\is_null($this->rootNodeMenuItem)) {
557
            $rootNode = $this->domainConfiguration->getRootNode();
558
            if (!\is_null($rootNode)) {
559
                $nodeTranslation = $rootNode->getNodeTranslation(
560
                    $this->locale,
561
                    $this->includeOffline
562
                );
563
                $this->rootNodeMenuItem = new NodeMenuItem(
564
                    $rootNode,
565
                    $nodeTranslation,
0 ignored issues
show
Bug introduced by Wim Vandersmissen
It seems like $nodeTranslation defined by $rootNode->getNodeTransl... $this->includeOffline) on line 559 can be null; however, Kunstmaan\NodeBundle\Hel...MenuItem::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
566
                    false,
567
                    $this
568
                );
569
            } else {
570
                $this->rootNodeMenuItem = $this->breadCrumb[0];
571
            }
572
        }
573
574
        return $this->rootNodeMenuItem;
575
    }
576
577
    /**
578
     * @return bool
579
     */
580
    public function isIncludeOffline()
581
    {
582
        return $this->includeOffline;
583
    }
584
585
    /**
586
     * @return string
587
     */
588
    public function getPermission()
589
    {
590
        return $this->permission;
591
    }
592
593
    /**
594
     * @return BaseUser
595
     */
596
    public function getUser()
597
    {
598
        return $this->tokenStorage->getToken()->getUser();
599
    }
600
601
    /**
602
     * @return EntityManagerInterface
603
     */
604
    public function getEntityManager()
605
    {
606
        return $this->em;
607
    }
608
609
    /**
610
     * @return TokenStorageInterface
611
     */
612
    public function getTokenStorage()
613
    {
614
        return $this->tokenStorage;
615
    }
616
617
    /**
618
     * @return AclHelper
619
     */
620
    public function getAclHelper()
621
    {
622
        return $this->aclHelper;
623
    }
624
625
    /**
626
     * @return string
627
     */
628
    public function getLocale()
629
    {
630
        return $this->locale;
631
    }
632
633
    /**
634
     * @return bool
635
     */
636
    public function isIncludeHiddenFromNav()
637
    {
638
        return $this->includeHiddenFromNav;
639
    }
640
641
    /**
642
     * Check if provided slug is in active path
643
     *
644
     * @param string $slug
645
     *
646
     * @return bool
647
     */
648
    public function getActive($slug)
649
    {
650
        $bc = $this->getBreadCrumb();
651
        foreach ($bc as $bcItem) {
652
            if ($bcItem->getSlug() == $slug) {
653
                return true;
654
            }
655
        }
656
657
        return false;
658
    }
659
660
    /**
661
     * @return bool
662
     */
663
    public function isInitialized()
664
    {
665
        return $this->initialized;
666
    }
667
668
    /**
669
     * @return array
670
     */
671
    private function getTopNodeMenuItems()
672
    {
673
        $topNodeMenuItems = array();
674
        $topNodes = $this->childNodes[0];
675
        /* @var Node $topNode */
676 View Code Duplication
        foreach ($topNodes as $topNode) {
0 ignored issues
show
Bug introduced by Wim Vandersmissen
The expression $topNodes of type object<Kunstmaan\NodeBundle\Entity\Node> is not traversable.
Loading history...
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
677
            $nodeTranslation = $topNode->getNodeTranslation(
678
                $this->locale,
679
                $this->includeOffline
680
            );
681
            if (!\is_null($nodeTranslation)) {
682
                $topNodeMenuItems[] = new NodeMenuItem(
683
                    $topNode,
684
                    $nodeTranslation,
685
                    null,
686
                    $this
687
                );
688
            }
689
        }
690
691
        return $topNodeMenuItems;
692
    }
693
}
694