Completed
Push — master ( 55dbed...4e3396 )
by Piotr
12s
created

ElementVoter::matchItem()   C

Complexity

Conditions 7
Paths 9

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
c 0
b 0
f 0
rs 6.7272
cc 7
eloc 14
nc 9
nop 1
1
<?php
2
3
/**
4
 * (c) FSi sp. z o.o. <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace FSi\Bundle\AdminBundle\Menu\KnpMenu;
11
12
use FSi\Bundle\AdminBundle\Admin\DependentElement;
13
use FSi\Bundle\AdminBundle\Admin\Element;
14
use FSi\Bundle\AdminBundle\Admin\ManagerInterface;
15
use FSi\Bundle\AdminBundle\Admin\RedirectableElement;
16
use Knp\Menu\ItemInterface;
17
use Knp\Menu\Matcher\Voter\VoterInterface;
18
use Symfony\Component\HttpFoundation\Request;
19
20
class ElementVoter implements VoterInterface
21
{
22
    /**
23
     * @var ManagerInterface
24
     */
25
    private $manager;
26
27
    /**
28
     * @var Request
29
     */
30
    private $request;
31
32
    public function __construct(ManagerInterface $manager)
33
    {
34
        $this->manager = $manager;
35
    }
36
37
    /**
38
     * @param Request $request
39
     */
40
    public function setRequest(Request $request)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
41
    {
42
        $this->request = $request;
43
    }
44
45
    /**
46
     * @inheritdoc
47
     */
48
    public function matchItem(ItemInterface $item)
49
    {
50
        if (!$this->validateRequestElement()) {
51
            return null;
52
        }
53
54
        $element = $this->getRequestElement();
55
56
        while (true) {
57
            foreach ($item->getExtra('routes', []) as $testedRoute) {
58
                if ($this->isRouteMatchingElement($element, $testedRoute['parameters'])) {
59
                    return true;
60
                }
61
            }
62
63
            if (!($element instanceof DependentElement)) {
64
                break;
65
            }
66
67
            if (!$this->manager->hasElement($element->getParentId())) {
68
                break;
69
            }
70
71
            $element = $this->manager->getElement($element->getParentId());
72
        }
73
74
        return false;
75
    }
76
77
    /**
78
     * @return bool
79
     */
80
    private function validateRequestElement()
81
    {
82
        if (empty($this->request->attributes)) {
83
            return false;
84
        }
85
86
        if (!$this->request->attributes->has('element')) {
87
            return false;
88
        }
89
90
        $element = $this->request->attributes->get('element');
91
        if (!($element instanceof Element)) {
92
            return false;
93
        }
94
95
        return true;
96
    }
97
98
    /**
99
     * @return Element
100
     */
101
    private function getRequestElement()
102
    {
103
        return $this->request->attributes->get('element');
104
    }
105
106
    /**
107
     * @param Element $element
108
     * @param array $testedRouteParameters
109
     * @return bool
110
     */
111
    private function isRouteMatchingElement(Element $element, array $testedRouteParameters)
112
    {
113
        return $this->isRouteMatchingElementDirectly($element, $testedRouteParameters) ||
114
            $this->isRouteMatchingElementAfterSuccess($element, $testedRouteParameters);
115
    }
116
117
    /**
118
     * @param Element $element
119
     * @param array $testedRouteParameters
120
     * @return bool
121
     */
122
    private function isRouteMatchingElementDirectly(Element $element, array $testedRouteParameters)
123
    {
124
        if (!isset($testedRouteParameters['element'])) {
125
            return false;
126
        }
127
128
        return $testedRouteParameters['element'] === $element->getId();
129
    }
130
131
    /**
132
     * @param Element $element
133
     * @param array $testedRouteParameters
134
     * @return bool
135
     */
136
    private function isRouteMatchingElementAfterSuccess(Element $element, array $testedRouteParameters)
137
    {
138
        if (!($element instanceof RedirectableElement)) {
139
            return false;
140
        }
141
142
        if (!isset($testedRouteParameters['element'])) {
143
            return false;
144
        }
145
146
        $successParameters = $element->getSuccessRouteParameters();
147
        if (!isset($successParameters['element'])) {
148
            return false;
149
        }
150
151
        return $successParameters['element'] === $testedRouteParameters['element'];
152
    }
153
}
154