Completed
Push — master ( aba493...5356ed )
by Ruud
315:38 queued 305:00
created

Kunstmaan/AdminBundle/Helper/Menu/MenuBuilder.php (2 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[]
15
     */
16
    private $adaptors = array();
17
18
    /**
19
     * @var MenuAdaptorInterface[]
20
     */
21
    private $sorted = array();
22
23
    /**
24
     * @var TopMenuItem[]
25
     */
26
    private $topMenuItems = null;
27
28
    /**
29
     * @var ContainerInterface
30
     */
31
    private $container;
32
33
    /**
34
     * @var MenuItem|null
35
     */
36
    private $currentCache = null;
37
38
    /**
39
     * Constructor
40
     *
41
     * @param ContainerInterface $container The container
42
     */
43 6
    public function __construct(ContainerInterface $container)
44
    {
45 6
        $this->container = $container;
46 6
    }
47
48
    /**
49
     * Add menu adaptor
50
     *
51
     * @param MenuAdaptorInterface $adaptor
52
     */
53 2
    public function addAdaptMenu(MenuAdaptorInterface $adaptor, $priority = 0)
54
    {
55 2
        $this->adaptors[$priority][] = $adaptor;
56 2
        unset($this->sorted);
57 2
    }
58
59
    /**
60
     * Get current menu item
61
     *
62
     * @return MenuItem|null
63
     */
64 4
    public function getCurrent()
65
    {
66 4
        if ($this->currentCache !== null) {
67 1
            return $this->currentCache;
68
        }
69
        /* @var $active MenuItem */
70 4
        $active = null;
71
        do {
72
            /* @var MenuItem[] $children */
73 4
            $children = $this->getChildren($active);
74 4
            $foundActiveChild = false;
75 4
            foreach ($children as $child) {
76 4
                if ($child->getActive()) {
77 3
                    $foundActiveChild = true;
78 3
                    $active = $child;
79
80 3
                    break;
81
                }
82
            }
83 4
        } while ($foundActiveChild);
84 4
        $this->currentCache = $active;
85
86 4
        return $active;
87
    }
88
89
    /**
90
     * Get breadcrumb path for current menu item
91
     *
92
     * @return MenuItem[]
93
     */
94 1
    public function getBreadCrumb()
95
    {
96 1
        $result = array();
97 1
        $current = $this->getCurrent();
98 1
        while (!is_null($current)) {
99 1
            array_unshift($result, $current);
100 1
            $current = $current->getParent();
101
        }
102
103 1
        return $result;
104
    }
105
106
    /**
107
     * Get top parent menu of current menu item
108
     *
109
     * @return TopMenuItem|null
110
     */
111 3
    public function getLowestTopChild()
112
    {
113 3
        $current = $this->getCurrent();
114 3
        while (!is_null($current)) {
115 2
            if ($current instanceof TopMenuItem) {
116 2
                return $current;
117
            }
118 1
            $current = $current->getParent();
119
        }
120
121 1
        return null;
122
    }
123
124
    /**
125
     * Get all top menu items
126
     *
127
     * @return MenuItem[]
128
     */
129 2
    public function getTopChildren()
130
    {
131 2
        if (is_null($this->topMenuItems)) {
132
            /* @var $request Request */
133 2
            $request = $this->container->get('request_stack')->getCurrentRequest();
134 2
            $this->topMenuItems = array();
135 2
            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...
136 2
                $menuAdaptor->adaptChildren($this, $this->topMenuItems, null, $request);
137
            }
138
        }
139
140 2
        return $this->topMenuItems;
141
    }
142
143
    /**
144
     * Get immediate children of the specified menu item
145
     *
146
     * @param MenuItem $parent
147
     *
148
     * @return MenuItem[]
149
     */
150 1
    public function getChildren(MenuItem $parent = null)
151
    {
152 1
        if ($parent === null) {
153 1
            return $this->getTopChildren();
154
        }
155
        /* @var $request Request */
156 1
        $request = $this->container->get('request_stack')->getCurrentRequest();
157 1
        $result = array();
158 1
        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...
159 1
            $menuAdaptor->adaptChildren($this, $result, $parent, $request);
160
        }
161
162 1
        return $result;
163
    }
164
165 2
    private function getAdaptors()
166
    {
167 2
        if (!isset($this->sorted)) {
168 2
            $this->sortAdaptors();
169
        }
170
171 2
        return $this->sorted;
172
    }
173
174
    /**
175
     * Sorts the internal list of adaptors by priority.
176
     */
177 2 View Code Duplication
    private function sortAdaptors()
178
    {
179 2
        $this->sorted = array();
180
181 2
        if (isset($this->adaptors)) {
182 2
            krsort($this->adaptors);
183 2
            $this->sorted = call_user_func_array('array_merge', $this->adaptors);
184
        }
185 2
    }
186
}
187