Completed
Push — master ( 2b45da...60f6b8 )
by Arnaud
16s queued 12s
created

AdminExtension   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Test Coverage

Coverage 18.45%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 67
c 1
b 0
f 0
dl 0
loc 171
ccs 12
cts 65
cp 0.1845
rs 10
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getApplicationParameter() 0 6 1
A __construct() 0 10 1
A getFunctions() 0 8 1
A dumpScripts() 0 5 1
B getMenuAction() 0 42 8
A isAdminActionAllowed() 0 5 1
A getAdminUrl() 0 28 4
1
<?php
2
3
namespace LAG\AdminBundle\Bridge\Twig\Extension;
4
5
use Doctrine\Common\Collections\Collection;
6
use LAG\AdminBundle\Assets\Registry\ScriptRegistryInterface;
7
use LAG\AdminBundle\Configuration\ApplicationConfigurationStorage;
8
use LAG\AdminBundle\Configuration\MenuItemConfiguration;
9
use LAG\AdminBundle\Exception\Exception;
10
use LAG\AdminBundle\Factory\ConfigurationFactory;
11
use LAG\AdminBundle\Routing\RoutingLoader;
12
use LAG\AdminBundle\View\ViewInterface;
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
use Symfony\Component\Routing\RouterInterface;
15
use Twig\Extension\AbstractExtension;
16
use Twig\TwigFunction;
17
18
class AdminExtension extends AbstractExtension
19
{
20
    /**
21
     * @var RouterInterface
22
     */
23
    private $router;
24
25
    /**
26
     * @var ConfigurationFactory
27
     */
28
    private $configurationFactory;
29
30
    /**
31
     * @var ApplicationConfigurationStorage
32
     */
33
    private $applicationConfigurationStorage;
34
35
    /**
36
     * @var ScriptRegistryInterface
37
     */
38
    private $scriptRegistry;
39
40
    /**
41
     * AdminExtension constructor.
42
     */
43 2
    public function __construct(
44
        ApplicationConfigurationStorage $applicationConfigurationStorage,
45
        RouterInterface $router,
46
        ConfigurationFactory $configurationFactory,
47
        ScriptRegistryInterface $scriptRegistry
48
    ) {
49 2
        $this->router = $router;
50 2
        $this->configurationFactory = $configurationFactory;
51 2
        $this->applicationConfigurationStorage = $applicationConfigurationStorage;
52 2
        $this->scriptRegistry = $scriptRegistry;
53 2
    }
54
55 2
    public function getFunctions(): array
56
    {
57
        return [
58 2
            new TwigFunction('admin_config', [$this, 'getApplicationParameter']),
59 2
            new TwigFunction('admin_menu_action', [$this, 'getMenuAction']),
60 2
            new TwigFunction('admin_url', [$this, 'getAdminUrl']),
61 2
            new TwigFunction('admin_action_allowed', [$this, 'isAdminActionAllowed']),
62 2
            new TwigFunction('admin_dump_scripts', [$this, 'dumpScripts']),
63
        ];
64
    }
65
66
    public function getApplicationParameter($name)
67
    {
68
        return $this
69
            ->applicationConfigurationStorage
70
            ->getConfiguration()
71
            ->get($name)
72
        ;
73
    }
74
75
    /**
76
     * Return the url of an menu item.
77
     *
78
     * @param ViewInterface         $view
79
     *
80
     * @throws Exception
81
     */
82
    public function getMenuAction(MenuItemConfiguration $configuration, ViewInterface $view = null): string
83
    {
84
        if ($configuration->getParameter('url')) {
85
            return $configuration->getParameter('url');
86
        }
87
        $routeName = $configuration->getParameter('route');
88
89
        if ($configuration->getParameter('admin')) {
90
            $routeName = RoutingLoader::generateRouteName(
91
                $configuration->getParameter('admin'),
92
                $configuration->getParameter('action'),
93
                $this
94
                    ->applicationConfigurationStorage
95
                    ->getConfiguration()
96
                    ->getParameter('routing_name_pattern')
97
            );
98
        }
99
        // Map the potential parameters to the entity
100
        $routeParameters = [];
101
        $configuredParameters = $configuration->getParameter('parameters');
102
103
        if (0 !== count($configuredParameters)) {
104
            if (null === $view) {
105
                throw new Exception('A view should be provided if the menu item route requires parameters');
106
            }
107
108
            if (!$view->getEntities() instanceof Collection) {
109
                throw new Exception('Entities returned by the view should be a instance of "'.Collection::class.'" to be used in menu action');
110
            }
111
112
            if (1 !== $view->getEntities()->count()) {
113
                throw new Exception('You can not map route parameters if multiple entities are loaded');
114
            }
115
            $entity = $view->getEntities()->first();
116
            $accessor = PropertyAccess::createPropertyAccessor();
117
118
            foreach ($configuredParameters as $name => $requirements) {
119
                $routeParameters[$name] = $accessor->getValue($entity, $name);
120
            }
121
        }
122
123
        return $this->router->generate($routeName, $routeParameters);
124
    }
125
126
    /**
127
     * Return the url of an Admin action.
128
     *
129
     * @param mixed|null    $entity
130
     *
131
     * @return string
132
     *
133
     * @throws Exception
134
     */
135
    public function getAdminUrl(ViewInterface $view, string $actionName, $entity = null)
136
    {
137
        if (!$this->isAdminActionAllowed($view, $actionName)) {
138
            throw new Exception('The action "'.$actionName.'" is not allowed for the admin "'.$view->getName().'"');
139
        }
140
        $configuration = $view->getAdminConfiguration();
141
        $parameters = [];
142
        $routeName = RoutingLoader::generateRouteName(
143
            $view->getName(),
144
            $actionName,
145
            $configuration->getParameter('routing_name_pattern')
146
        );
147
148
        if (null !== $entity) {
149
            $accessor = PropertyAccess::createPropertyAccessor();
150
            $actionConfiguration = $this->configurationFactory->createActionConfiguration(
151
                $actionName,
152
                $configuration->getParameter('actions')[$actionName],
153
                $view->getName(),
154
                $view->getAdminConfiguration()
155
            );
156
157
            foreach ($actionConfiguration->getParameter('route_requirements') as $name => $requirements) {
158
                $parameters[$name] = $accessor->getValue($entity, $name);
159
            }
160
        }
161
162
        return $this->router->generate($routeName, $parameters);
163
    }
164
165
    /**
166
     * Return true if the given action is allowed for the given Admin.
167
     *
168
     * @return bool
169
     */
170
    public function isAdminActionAllowed(ViewInterface $view, string $actionName)
171
    {
172
        $configuration = $view->getAdminConfiguration();
173
174
        return key_exists($actionName, $configuration->getParameter('actions'));
175
    }
176
177
    /**
178
     * Dump the scripts according to the location (usually head or footer).
179
     *
180
     * @param string $location
181
     *
182
     * @return string
183
     */
184
    public function dumpScripts($location)
185
    {
186
        return $this
187
            ->scriptRegistry
188
            ->dump($location)
189
        ;
190
    }
191
}
192