Completed
Push — master ( 91fdab...75a7b9 )
by
unknown
13:37
created

Kunstmaan/AdminBundle/Helper/Menu/MenuBuilder.php (4 issues)

Upgrade to new PHP Analysis Engine

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\AdminBundle\Helper\Menu;
4
5
use Symfony\Component\DependencyInjection\ContainerInterface;
6
use Symfony\Component\HttpFoundation\Request;
7
8
/**
9
 * The MenuBuilder will build the top menu and the side menu of the admin interface
10
 */
11
class MenuBuilder
12
{
13
    /**
14
     * @var MenuAdaptorInterface[] $adaptors
15
     */
16
    private $adaptors = array();
17
18
    /**
19
     * @var MenuAdaptorInterface[] $adaptors
20
     */
21
    private $sorted = array();
22
23
    /**
24
     * @var TopMenuItem[] $topMenuItems
25
     */
26
    private $topMenuItems = null;
27
28
    /**
29
     * @var ContainerInterface $container
30
     */
31
    private $container;
32
33
    /**
34
     * @var MenuItem|null
35
     */
36
    private $currentCache = null;
37
38
39
    /**
40
     * Constructor
41
     *
42
     * @param ContainerInterface $container The container
43
     */
44
    public function __construct(ContainerInterface $container)
45
    {
46
        $this->container = $container;
47
    }
48
49
    /**
50
     * Add menu adaptor
51
     *
52
     * @param MenuAdaptorInterface $adaptor
53
     */
54
    public function addAdaptMenu(MenuAdaptorInterface $adaptor, $priority = 0)
55
    {
56
        $this->adaptors[$priority][] = $adaptor;
57
        unset($this->sorted);
58
    }
59
60
    /**
61
     * Get current menu item
62
     *
63
     * @return MenuItem|null
64
     */
65
    public function getCurrent()
66
    {
67
        if ($this->currentCache !== null) {
68
            return $this->currentCache;
69
        }
70
        /* @var $active MenuItem */
71
        $active = null;
72
        do {
73
            /* @var MenuItem[] $children */
74
            $children         = $this->getChildren($active);
75
            $foundActiveChild = false;
76
            foreach ($children as $child) {
77
                if ($child->getActive()) {
78
                    $foundActiveChild = true;
79
                    $active           = $child;
80
                    break;
81
                }
82
            }
83
        } while ($foundActiveChild);
84
        $this->currentCache = $active;
85
86
        return $active;
87
    }
88
89
    /**
90
     * Get breadcrumb path for current menu item
91
     *
92
     * @return MenuItem[]
93
     */
94
    public function getBreadCrumb()
95
    {
96
        $result  = array();
97
        $current = $this->getCurrent();
98
        while (!is_null($current)) {
99
            array_unshift($result, $current);
100
            $current = $current->getParent();
101
        }
102
103
        return $result;
104
    }
105
106
    /**
107
     * Get top parent menu of current menu item
108
     *
109
     * @return TopMenuItem|null
110
     */
111
    public function getLowestTopChild()
112
    {
113
        $current = $this->getCurrent();
114
        while (!is_null($current)) {
115
116
            if ($current instanceof TopMenuItem) {
117
                return $current;
118
            }
119
            $current = $current->getParent();
120
        }
121
122
        return null;
123
    }
124
125
    /**
126
     * Get all top menu items
127
     *
128
     * @return MenuItem[]
129
     */
130
    public function getTopChildren()
131
    {
132
        if (is_null($this->topMenuItems)) {
133
            /* @var $request Request */
134
            $request            = $this->container->get('request_stack')->getCurrentRequest();
135
            $this->topMenuItems = array();
136
            foreach ($this->getAdaptors() as $menuAdaptor) {
0 ignored issues
show
The expression $this->getAdaptors() of type null|array<integer,objec...\MenuAdaptorInterface>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
137
                $menuAdaptor->adaptChildren($this, $this->topMenuItems, null, $request);
138
            }
139
        }
140
141
        return $this->topMenuItems;
142
    }
143
144
    /**
145
     * Get immediate children of the specified menu item
146
     *
147
     * @param MenuItem $parent
148
     *
149
     * @return MenuItem[]
150
     */
151
    public function getChildren(MenuItem $parent = null)
152
    {
153
        if ($parent === null) {
154
            return $this->getTopChildren();
155
        }
156
        /* @var $request Request */
157
        $request = $this->container->get('request_stack')->getCurrentRequest();
158
        $result  = array();
159
        foreach ($this->getAdaptors() as $menuAdaptor) {
0 ignored issues
show
The expression $this->getAdaptors() of type null|array<integer,objec...\MenuAdaptorInterface>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
160
            $menuAdaptor->adaptChildren($this, $result, $parent, $request);
161
        }
162
163
        return $result;
164
    }
165
166
    private function getAdaptors()
167
    {
168
        if (!isset($this->sorted)) {
169
            $this->sortAdaptors();
170
        }
171
172
        return $this->sorted;
173
    }
174
175
    /**
176
     * Sorts the internal list of adaptors by priority.
177
     */
178 View Code Duplication
    private function sortAdaptors()
0 ignored issues
show
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...
179
    {
180
        $this->sorted = array();
181
182
        if (isset($this->adaptors)) {
183
            krsort($this->adaptors);
184
            $this->sorted = call_user_func_array('array_merge', $this->adaptors);
0 ignored issues
show
Documentation Bug introduced by
It seems like call_user_func_array('ar...erge', $this->adaptors) of type * is incompatible with the declared type array<integer,object<Kun...\MenuAdaptorInterface>> of property $sorted.

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...
185
        }
186
    }
187
}
188