Test Failed
Push — master ( 3eb0e4...9196b6 )
by Ivan
02:13
created

BasicNavigation::process()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.439
c 0
b 0
f 0
cc 5
eloc 15
nc 5
nop 3
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Everlution\Navigation\Navigation;
6
7
use Everlution\Navigation\Item;
8
use Everlution\Navigation\Matcher\Matcher;
9
use Everlution\Navigation\NavigationItem;
10
use Everlution\Navigation\RootNavigationItem;
11
12
/**
13
 * Class BasicNavigation.
14
 * @author Ivan Barlog <[email protected]>
15
 */
16
class BasicNavigation implements Navigation
17
{
18
    const DEFAULT_MAX_LEVEL = 3;
19
20
    /** @var NavigationItem[] */
21
    private $ancestors = [];
22
    /** @var NavigationItem */
23
    private $current = null;
24
    /** @var int */
25
    private $maxLevel;
26
    /** @var RootNavigationItem */
27
    private $root;
28
29
    public function __construct(RootNavigationItem $root, Matcher $matcher, int $maxLevel = self::DEFAULT_MAX_LEVEL)
30
    {
31
        $this->maxLevel = $maxLevel;
32
        $this->process($root, $matcher);
33
        $this->root = $root;
0 ignored issues
show
Documentation Bug introduced by
$root is of type object<Everlution\Navigation\Item>, but the property $root was declared to be of type object<Everlution\Navigation\RootNavigationItem>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
34
    }
35
36
    public function getRoot()
37
    {
38
        return $this->root;
39
    }
40
41
    /**
42
     * @param NavigationItem $item
43
     * @return bool
44
     */
45
    public function isAncestor(NavigationItem $item): bool
46
    {
47
        $ancestors = $this->ancestors;
48
        array_pop($ancestors);
49
50
        return in_array($item, $ancestors);
51
    }
52
53
    /**
54
     * @param NavigationItem $item
55
     * @return bool
56
     */
57
    public function isCurrent(NavigationItem $item): bool
58
    {
59
        return $this->getCurrent() === $item;
60
    }
61
62
    /**
63
     * @return array
64
     */
65
    public function getBreadcrumbs(): array
66
    {
67
        return $this->ancestors;
68
    }
69
70
    /**
71
     * @return NavigationItem
72
     * @throws CurrentItemNotMatchedException
73
     */
74
    public function getCurrent(): NavigationItem
75
    {
76
        if (!$this->current instanceof NavigationItem) {
77
            throw new CurrentItemNotMatchedException();
78
        }
79
80
        return $this->current;
81
    }
82
83
    /**
84
     * @param Item $item
85
     * @param Matcher $matcher
86
     * @param int $depth
87
     * @return Item|null
88
     */
89
    private function process(Item &$item, Matcher &$matcher, int $depth = 0)
90
    {
91
        if ($depth > $this->maxLevel) {
92
            return null;
93
        }
94
95
        $this->ancestors[$depth] = $item;
96
97
        if ($matcher->isCurrent($item)) {
98
            $this->current = $item;
0 ignored issues
show
Documentation Bug introduced by
$item is of type object<Everlution\Navigation\Item>, but the property $current was declared to be of type object<Everlution\Navigation\NavigationItem>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
99
            array_shift($this->ancestors);
100
101
            return $item;
102
        }
103
104
        $childDepth = ++$depth;
105
        /** @var NavigationItem $child */
106
        foreach ($item->getChildren() as $child) {
107
            $result = $this->process($child, $matcher, $childDepth);
108
109
            if ($result instanceof NavigationItem) {
110
                return $result;
111
            }
112
        }
113
114
        unset($this->ancestors[$depth]);
115
116
        return null;
117
    }
118
}
119