Completed
Push — master ( 461592...b2f345 )
by Łukasz
14s queued 10s
created

ElementVoter::getRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
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
declare(strict_types=1);
11
12
namespace FSi\Bundle\AdminBundle\Menu\KnpMenu;
13
14
use FSi\Bundle\AdminBundle\Admin\DependentElement;
15
use FSi\Bundle\AdminBundle\Admin\Element;
16
use FSi\Bundle\AdminBundle\Admin\ManagerInterface;
17
use FSi\Bundle\AdminBundle\Admin\RedirectableElement;
18
use Knp\Menu\ItemInterface;
19
use Knp\Menu\Matcher\Voter\VoterInterface;
20
use Symfony\Component\HttpFoundation\RequestStack;
21
22
class ElementVoter implements VoterInterface
23
{
24
    /**
25
     * @var ManagerInterface
26
     */
27
    private $manager;
28
29
    /**
30
     * @var RequestStack
31
     */
32
    private $requestStack;
33
34
    public function __construct(ManagerInterface $manager, RequestStack $requestStack)
35
    {
36
        $this->manager = $manager;
37
        $this->requestStack = $requestStack;
38
    }
39
40
    public function matchItem(ItemInterface $item)
41
    {
42
        if (!$this->validateRequestElement()) {
43
            return null;
44
        }
45
46
        $element = $this->getRequestElement();
47
48
        while (true) {
49
            /** @var array $routes */
50
            $routes = $item->getExtra('routes', []);
51
            foreach ($routes as $testedRoute) {
52
                if ($this->isRouteMatchingElement($element, $testedRoute['parameters'])) {
53
                    return true;
54
                }
55
            }
56
57
            if (!($element instanceof DependentElement)) {
58
                break;
59
            }
60
61
            if (!$this->manager->hasElement($element->getParentId())) {
62
                break;
63
            }
64
65
            $element = $this->manager->getElement($element->getParentId());
66
        }
67
68
        return false;
69
    }
70
71
    private function validateRequestElement(): bool
72
    {
73
        if (!$this->getRequest()->attributes->has('element')) {
74
            return false;
75
        }
76
77
        $element = $this->getRequest()->attributes->get('element');
78
        if (!($element instanceof Element)) {
79
            return false;
80
        }
81
82
        return true;
83
    }
84
85
    private function getRequestElement(): Element
86
    {
87
        return $this->getRequest()->attributes->get('element');
88
    }
89
90
    private function isRouteMatchingElement(Element $element, array $testedRouteParameters): bool
91
    {
92
        return $this->isRouteMatchingElementDirectly($element, $testedRouteParameters) ||
93
            $this->isRouteMatchingElementAfterSuccess($element, $testedRouteParameters);
94
    }
95
96
    private function isRouteMatchingElementDirectly(Element $element, array $testedRouteParameters): bool
97
    {
98
        if (!isset($testedRouteParameters['element'])) {
99
            return false;
100
        }
101
102
        return $testedRouteParameters['element'] === $element->getId();
103
    }
104
105
    private function isRouteMatchingElementAfterSuccess(Element $element, array $testedRouteParameters): bool
106
    {
107
        if (!($element instanceof RedirectableElement)) {
108
            return false;
109
        }
110
111
        if (!isset($testedRouteParameters['element'])) {
112
            return false;
113
        }
114
115
        $successParameters = $element->getSuccessRouteParameters();
116
        if (!isset($successParameters['element'])) {
117
            return false;
118
        }
119
120
        return $successParameters['element'] === $testedRouteParameters['element'];
121
    }
122
123
    private function getRequest()
124
    {
125
        return $this->requestStack->getCurrentRequest();
126
    }
127
}
128