Completed
Push — master ( e8bfce...313e31 )
by Arnaud
13s queued 11s
created

AdminSubscriber::createView()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 43
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 6.015

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 32
c 1
b 0
f 0
nc 8
nop 1
dl 0
loc 43
ccs 21
cts 32
cp 0.6563
crap 6.015
rs 9.0968
1
<?php
2
3
namespace LAG\AdminBundle\Event\Subscriber;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use LAG\AdminBundle\Admin\ActionInterface;
7
use LAG\AdminBundle\Admin\AdminInterface;
8
use LAG\AdminBundle\Admin\Helper\AdminHelperInterface;
9
use LAG\AdminBundle\Configuration\AdminConfiguration;
10
use LAG\AdminBundle\Event\Events;
11
use LAG\AdminBundle\Event\Events\AdminEvent;
12
use LAG\AdminBundle\Event\Events\EntityEvent;
13
use LAG\AdminBundle\Event\Events\ViewEvent;
14
use LAG\AdminBundle\Exception\Exception;
15
use LAG\AdminBundle\Factory\ActionFactory;
16
use LAG\AdminBundle\Factory\DataProviderFactory;
17
use LAG\AdminBundle\Factory\ViewFactory;
18
use LAG\AdminBundle\LAGAdminBundle;
19
use LAG\AdminBundle\Routing\RoutingLoader;
20
use LAG\AdminBundle\Utils\TranslationUtils;
21
use LAG\AdminBundle\View\RedirectView;
22
use LAG\AdminBundle\View\ViewHelper;
23
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
24
use Symfony\Component\HttpFoundation\Request;
25
use Symfony\Component\HttpFoundation\Session\Session;
26
use Symfony\Component\HttpFoundation\Session\SessionInterface;
27
use Symfony\Component\Routing\RouterInterface;
28
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
29
use Symfony\Contracts\Translation\TranslatorInterface;
30
31
class AdminSubscriber implements EventSubscriberInterface
32
{
33
    /**
34
     * @var ActionFactory
35
     */
36
    private $actionFactory;
37
38
    /**
39
     * @var ViewFactory
40
     */
41
    private $viewFactory;
42
43
    /**
44
     * @var EventDispatcherInterface
45
     */
46
    private $eventDispatcher;
47
48
    /**
49
     * @var DataProviderFactory
50
     */
51
    private $dataProviderFactory;
52
53
    /**
54
     * @var Session|SessionInterface
55
     */
56
    private $session;
57
58
    /**
59
     * @var TranslatorInterface
60
     */
61
    private $translator;
62
63
    /**
64
     * @var RouterInterface
65
     */
66
    private $router;
67
68
    /**
69
     * @var AdminHelperInterface
70
     */
71
    private $helper;
72
73
    /**
74
     * @return array
75
     */
76 6
    public static function getSubscribedEvents()
77
    {
78
        return [
79 6
            Events::ADMIN_HANDLE_REQUEST => 'handleRequest',
80
            Events::ADMIN_VIEW => 'createView',
81
            Events::ENTITY_LOAD => [
82
                'loadEntities', 255,
83
            ],
84
            Events::ENTITY_SAVE => 'saveEntity',
85
        ];
86
    }
87
88
    /**
89
     * AdminSubscriber constructor.
90
     */
91 24
    public function __construct(
92
        ActionFactory $actionFactory,
93
        ViewFactory $viewFactory,
94
        DataProviderFactory $dataProviderFactory,
95
        EventDispatcherInterface $eventDispatcher,
96
        SessionInterface $session,
97
        TranslatorInterface $translator,
98
        RouterInterface $router,
99
        AdminHelperInterface $helper
100
    ) {
101 24
        $this->actionFactory = $actionFactory;
102 24
        $this->viewFactory = $viewFactory;
103 24
        $this->eventDispatcher = $eventDispatcher;
104 24
        $this->dataProviderFactory = $dataProviderFactory;
105 24
        $this->session = $session;
106 24
        $this->translator = $translator;
107 24
        $this->router = $router;
108 24
        $this->helper = $helper;
109 24
    }
110
111
    /**
112
     * Define the current action according to the routing configuration.
113
     *
114
     * @throws Exception
115
     */
116 4
    public function handleRequest(AdminEvent $event)
117
    {
118 4
        $actionName = $event->getRequest()->get('_action');
119
120 4
        if (null === $actionName) {
121 2
            throw new Exception('The _action was not found in the request');
122
        }
123 2
        $admin = $event->getAdmin();
124 2
        $this->helper->setCurrent($admin);
125 2
        $action = $this->actionFactory->create($actionName, $admin->getName(), $admin->getConfiguration());
126
127 2
        $event->setAction($action);
128 2
    }
129
130
    /**
131
     * Create a view using the view factory.
132
     */
133 8
    public function createView(ViewEvent $event)
134
    {
135 8
        $admin = $event->getAdmin();
136 8
        $action = $admin->getAction();
137 8
        $formName = '';
138
139
        // The form name is different according to the current action
140 8
        if ('edit' === $action->getName()) {
141 4
            $formName = 'entity';
142 4
        } elseif ('create' === $action->getName()) {
143 2
            $formName = 'entity';
144 2
        } elseif ('delete' === $action->getName()) {
145 2
            $formName = 'delete';
146
        }
147 8
        $viewHelper = new ViewHelper();
148
149 8
        if ($viewHelper->shouldRedirect($event->getRequest(), $admin->getConfiguration(), $admin, $action, $formName)) {
150
            $url = $this->getRedirectionUrl(
151
                $admin,
152
                $action,
153
                $admin->getConfiguration(),
154
                $event->getRequest()
155
            );
156
157
            $view = new RedirectView(
158
                $action->getName(),
159
                $admin->getName(),
160
                $action->getConfiguration(),
161
                $admin->getConfiguration()
162
            );
163
            $view->setUrl($url);
164
        } else {
165 8
            $view = $this->viewFactory->create(
166 8
                $event->getRequest(),
167 8
                $action->getName(),
168 8
                $admin->getName(),
169 8
                $admin->getConfiguration(),
170 8
                $action->getConfiguration(),
171 8
                $admin->getEntities(),
172 8
                $admin->getForms()
173
            );
174
        }
175 8
        $event->setView($view);
176 8
    }
177
178
    /**
179
     * Load entities into the event data to pass them to the Admin.
180
     *
181
     * @throws Exception
182
     */
183 8
    public function loadEntities(EntityEvent $event)
184
    {
185 8
        $admin = $event->getAdmin();
186 8
        $configuration = $admin->getConfiguration();
187 8
        $actionConfiguration = $admin->getAction()->getConfiguration();
188
189 8
        $dataProvider = $this->dataProviderFactory->get($configuration->getParameter('data_provider'));
190 8
        $strategy = $actionConfiguration->getParameter('load_strategy');
191 8
        $class = $configuration->getParameter('entity');
192
193 8
        if (LAGAdminBundle::LOAD_STRATEGY_NONE === $strategy) {
194 2
            return;
195 6
        } elseif (LAGAdminBundle::LOAD_STRATEGY_MULTIPLE === $strategy) {
196 2
            $entities = $dataProvider->getCollection($admin, $event->getFilters());
197 2
            $event->setEntities($entities);
198 4
        } elseif (LAGAdminBundle::LOAD_STRATEGY_UNIQUE === $strategy) {
199 4
            $requirements = $actionConfiguration->getParameter('route_requirements');
200 4
            $identifier = null;
201
202 4
            foreach ($requirements as $name => $requirement) {
203 4
                if (null !== $event->getRequest()->get($name)) {
204 2
                    $identifier = $event->getRequest()->get($name);
205 2
                    break;
206
                }
207
            }
208
209 4
            if (null === $identifier) {
210 2
                throw new Exception('Unable to find a identifier for the class "'.$class.'"');
211
            }
212 2
            $entity = $dataProvider->get($admin, $identifier);
213
214 2
            $event->setEntities(new ArrayCollection([
215 2
                $entity,
216
            ]));
217
        }
218 4
    }
219
220
    /**
221
     * Save an entity.
222
     */
223 2
    public function saveEntity(EntityEvent $event)
224
    {
225 2
        $admin = $event->getAdmin();
226 2
        $configuration = $admin->getConfiguration();
227
228
        // Save the entity changes using the configured data provider
229
        $dataProvider = $this
230 2
            ->dataProviderFactory
231 2
            ->get($configuration->getParameter('data_provider'))
232
        ;
233 2
        $dataProvider->save($admin);
234
235
        // Inform the user that the save is successful
236 2
        $message = $this->translateMessage('saved', $admin->getName(), $configuration);
237
238
        $this
239 2
            ->session
240 2
            ->getFlashBag()
241 2
            ->add('success', $message)
242
        ;
243 2
    }
244
245 2
    private function translateMessage(string $message, string $adminName, AdminConfiguration $configuration): string
246
    {
247 2
        if (!$configuration->isTranslationEnabled()) {
248 2
            return $message;
249
        }
250
        $message = TranslationUtils::getTranslationKey($configuration->getTranslationPattern(), $adminName, $message);
251
252
        return $this->translator->trans($message, [], $configuration->getTranslationCatalog());
253
    }
254
255
    /**
256
     * Return the url where the user should be redirected to. An exception will be thrown if no url can be generated.
257
     *
258
     * @throws Exception
259
     */
260
    private function getRedirectionUrl(
261
        AdminInterface $admin,
262
        ActionInterface $action,
263
        AdminConfiguration $configuration,
264
        Request $request
265
    ): string {
266
        if ('edit' === $action->getName()) {
267
            $routeName = RoutingLoader::generateRouteName(
268
                $admin->getName(),
269
                'list',
270
                $configuration->get('routing_name_pattern')
271
            );
272
            $url = $this->router->generate($routeName);
273
274
            return $url;
275
        }
276
277
        // When the create form is submitted, the user should be redirected to the edit action after saving the form
278
        // data
279
        if ('create' === $action->getName()) {
280
            $targetAction = 'list';
281
            $routeParameters = [];
282
283
            if (!$request->get('submit_and_redirect')) {
284
                $targetAction = 'edit';
285
                $routeParameters = [
286
                    'id' => $admin->getEntities()->first()->getId(),
287
                ];
288
            }
289
            $routeName = RoutingLoader::generateRouteName(
290
                $admin->getName(),
291
                $targetAction,
292
                $configuration->get('routing_name_pattern')
293
            );
294
            $url = $this->router->generate($routeName, $routeParameters);
295
296
            return $url;
297
        }
298
299
        if ('delete' === $action->getName()) {
300
            $routeName = RoutingLoader::generateRouteName(
301
                $admin->getName(),
302
                'list',
303
                $configuration->get('routing_name_pattern')
304
            );
305
            $url = $this->router->generate($routeName);
306
307
            return $url;
308
        }
309
310
        throw new Exception('Unable to generate an redirection url for the current action');
311
    }
312
}
313