Completed
Pull Request — 5.6 (#2830)
by Jeroen
14:14
created

AdminListBundle/Controller/AdminListController.php (1 issue)

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\AdminListBundle\Controller;
4
5
use Doctrine\ORM\EntityManager;
6
use Kunstmaan\AdminBundle\Entity\EntityInterface;
7
use Kunstmaan\AdminBundle\Event\AdaptSimpleFormEvent;
8
use Kunstmaan\AdminBundle\Event\Events;
9
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
10
use Kunstmaan\AdminListBundle\AdminList\AdminList;
11
use Kunstmaan\AdminListBundle\AdminList\Configurator\AbstractAdminListConfigurator;
12
use Kunstmaan\AdminListBundle\AdminList\ItemAction\SimpleItemAction;
13
use Kunstmaan\AdminListBundle\AdminList\SortableInterface;
14
use Kunstmaan\AdminListBundle\Entity\LockableEntityInterface;
15
use Kunstmaan\AdminListBundle\Event\AdminListEvent;
16
use Kunstmaan\AdminListBundle\Event\AdminListEvents;
17
use Kunstmaan\AdminListBundle\Service\EntityVersionLockService;
18
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
19
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
20
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
21
use Symfony\Component\HttpFoundation\RedirectResponse;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
25
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26
use Symfony\Component\PropertyAccess\PropertyAccess;
27
28
/**
29
 * AdminListController
30
 */
31
abstract class AdminListController extends Controller
32
{
33
    /**
34
     * You can override this method to return the correct entity manager when using multiple databases ...
35
     *
36
     * @return \Doctrine\Common\Persistence\ObjectManager|object
37
     */
38
    protected function getEntityManager()
39
    {
40
        return $this->getDoctrine()->getManager();
41
    }
42
43
    /**
44
     * Shows the list of entities
45
     *
46
     * @param Request|null $request
47
     *
48
     * @return Response
49
     */
50
    protected function doIndexAction(AbstractAdminListConfigurator $configurator, Request $request)
51
    {
52
        /* @var AdminList $adminList */
53
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createList($configurator);
54
        $adminList->bindRequest($request);
55
56
        $this->buildSortableFieldActions($configurator);
57
58
        return new Response(
59
            $this->renderView(
60
                $configurator->getListTemplate(),
61
                ['adminlist' => $adminList, 'adminlistconfigurator' => $configurator, 'addparams' => []]
62
            )
63
        );
64
    }
65
66
    /**
67
     * Export a list of Entities
68
     *
69
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
70
     * @param string                        $_format      The format to export to
71
     *
72
     * @throws AccessDeniedHttpException
73
     *
74
     * @return Response
75
     */
76
    protected function doExportAction(AbstractAdminListConfigurator $configurator, $_format, Request $request = null)
77
    {
78
        if (!$configurator->canExport()) {
79
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
80
        }
81
82
        /* @var AdminList $adminList */
83
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createExportList($configurator);
84
        $adminList->bindRequest($request);
85
86
        return $this->container->get('kunstmaan_adminlist.service.export')->getDownloadableResponse($adminList, $_format);
87
    }
88
89
    /**
90
     * Creates and processes the form to add a new Entity
91
     *
92
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
93
     * @param string                        $type         The type to add
94
     * @param Request|null                  $request
95
     *
96
     * @throws AccessDeniedHttpException
97
     *
98
     * @return Response
99
     */
100
    protected function doAddAction(AbstractAdminListConfigurator $configurator, $type = null, Request $request)
101
    {
102
        if (!$configurator->canAdd()) {
103
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
104
        }
105
106
        /* @var EntityManager $em */
107
        $em = $this->getEntityManager();
108
        $entityName = isset($type) ? $type : $configurator->getRepositoryName();
109
110
        $classMetaData = $em->getClassMetadata($entityName);
111
        // Creates a new instance of the mapped class, without invoking the constructor.
112
        $classname = $classMetaData->getName();
113
        $helper = new $classname();
114
        $helper = $configurator->decorateNewEntity($helper);
115
116
        $formType = $configurator->getAdminType($helper);
117
118
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
119
        $event = $this->container->get('event_dispatcher')->dispatch(Events::ADAPT_SIMPLE_FORM, $event);
120
        $tabPane = $event->getTabPane();
121
122
        $form = $this->createForm($formType, $helper, $event->getOptions());
123
124 View Code Duplication
        if ($request->isMethod('POST')) {
125
            if ($tabPane) {
126
                $tabPane->bindRequest($request);
127
                $form = $tabPane->getForm();
128
            } else {
129
                $form->handleRequest($request);
130
            }
131
132
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
133
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
134
                $adminListEvent = new AdminListEvent($helper, $request, $form);
135
                $this->container->get('event_dispatcher')->dispatch(
136
                    AdminListEvents::PRE_ADD,
137
                    $adminListEvent
138
                );
139
140
                // Check if Response is given
141
                if ($adminListEvent->getResponse() instanceof Response) {
142
                    return $adminListEvent->getResponse();
143
                }
144
145
                // Set sort weight
146
                $helper = $this->setSortWeightOnNewItem($configurator, $helper);
147
148
                $em->persist($helper);
149
                $em->flush();
150
                $this->container->get('event_dispatcher')->dispatch(
151
                    AdminListEvents::POST_ADD,
152
                    $adminListEvent
153
                );
154
155
                // Check if Response is given
156
                if ($adminListEvent->getResponse() instanceof Response) {
157
                    return $adminListEvent->getResponse();
158
                }
159
160
                $indexUrl = $configurator->getIndexUrl();
161
162
                return new RedirectResponse(
163
                    $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : [])
164
                );
165
            }
166
        }
167
168
        $params = [
169
            'form' => $form->createView(),
170
            'adminlistconfigurator' => $configurator,
171
            'entityVersionLockCheck' => false,
172
            'entity' => $helper,
173
        ];
174
175
        if ($tabPane) {
176
            $params = array_merge($params, ['tabPane' => $tabPane]);
177
        }
178
179
        return new Response(
180
            $this->renderView($configurator->getAddTemplate(), $params)
181
        );
182
    }
183
184
    /**
185
     * Creates and processes the edit form for an Entity using its ID
186
     *
187
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
188
     * @param string                        $entityId     The id of the entity that will be edited
189
     * @param Request|null                  $request
190
     *
191
     * @throws NotFoundHttpException
192
     * @throws AccessDeniedHttpException
193
     *
194
     * @return Response
195
     */
196
    protected function doEditAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
197
    {
198
        /* @var EntityManager $em */
199
        $em = $this->getEntityManager();
200
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
201
202
        if ($helper === null) {
203
            throw new NotFoundHttpException('Entity not found.');
204
        }
205
206
        if (!$configurator->canEdit($helper)) {
207
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
208
        }
209
210
        // This entity is locked
211
        if (($helper instanceof LockableEntityInterface) && $this->isLockableEntityLocked($helper)) {
212
            $indexUrl = $configurator->getIndexUrl();
213
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
214
            if (!$request->isXmlHttpRequest()) {
215
                /** @var EntityVersionLockService $entityVersionLockService */
216
                $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
217
218
                $user = $entityVersionLockService->getUsersWithEntityVersionLock($helper, $this->getUser());
219
                $message = $this->container->get('translator')->trans('kuma_admin_list.edit.flash.locked', ['%user%' => implode(', ', $user)]);
220
                $this->addFlash(
221
                    FlashTypes::WARNING,
222
                    $message
223
                );
224
225
                return new RedirectResponse(
226
                    $this->generateUrl(
227
                        $indexUrl['path'],
228
                        isset($indexUrl['params']) ? $indexUrl['params'] : []
229
                    )
230
                );
231
            }
232
        }
233
234
        $formType = $configurator->getAdminType($helper);
235
236
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
237
        $event = $this->container->get('event_dispatcher')->dispatch(Events::ADAPT_SIMPLE_FORM, $event);
238
        $tabPane = $event->getTabPane();
239
240
        $form = $this->createForm($formType, $helper, $event->getOptions());
241
242 View Code Duplication
        if ($request->isMethod('POST')) {
243
            if ($tabPane) {
244
                $tabPane->bindRequest($request);
245
                $form = $tabPane->getForm();
246
            } else {
247
                $form->handleRequest($request);
248
            }
249
250
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
251
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
252
                $adminListEvent = new AdminListEvent($helper, $request, $form);
253
                $this->container->get('event_dispatcher')->dispatch(
254
                    AdminListEvents::PRE_EDIT,
255
                    $adminListEvent
256
                );
257
258
                // Check if Response is given
259
                if ($adminListEvent->getResponse() instanceof Response) {
260
                    return $adminListEvent->getResponse();
261
                }
262
263
                $em->persist($helper);
264
                $em->flush();
265
                $this->container->get('event_dispatcher')->dispatch(
266
                    AdminListEvents::POST_EDIT,
267
                    $adminListEvent
268
                );
269
270
                // Check if Response is given
271
                if ($adminListEvent->getResponse() instanceof Response) {
272
                    return $adminListEvent->getResponse();
273
                }
274
275
                $indexUrl = $configurator->getIndexUrl();
276
277
                // Don't redirect to listing when coming from ajax request, needed for url chooser.
278
                if (!$request->isXmlHttpRequest()) {
279
                    return new RedirectResponse(
280
                        $this->generateUrl(
281
                            $indexUrl['path'],
282
                            isset($indexUrl['params']) ? $indexUrl['params'] : []
283
                        )
284
                    );
285
                }
286
            }
287
        }
288
289
        $configurator->buildItemActions();
290
291
        $params = [
292
            'form' => $form->createView(),
293
            'entity' => $helper, 'adminlistconfigurator' => $configurator,
294
            'entityVersionLockInterval' => $this->container->getParameter('kunstmaan_entity.lock_check_interval'),
295
            'entityVersionLockCheck' => $this->container->getParameter('kunstmaan_entity.lock_enabled') && $helper instanceof LockableEntityInterface,
296
        ];
297
298
        if ($tabPane) {
299
            $params = array_merge($params, ['tabPane' => $tabPane]);
300
        }
301
302
        return new Response(
303
            $this->renderView(
304
                $configurator->getEditTemplate(),
305
                $params
306
            )
307
        );
308
    }
309
310
    protected function doViewAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
311
    {
312
        /* @var EntityManager $em */
313
        $em = $this->getEntityManager();
314
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
0 ignored issues
show
The method findOneById() does not exist on Doctrine\Persistence\ObjectRepository. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
315
        if ($helper === null) {
316
            throw new NotFoundHttpException('Entity not found.');
317
        }
318
319
        if (!$configurator->canView($helper)) {
320
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
321
        }
322
323
        $MetaData = $em->getClassMetadata($configurator->getRepositoryName());
324
        $fields = [];
325
        $accessor = PropertyAccess::createPropertyAccessor();
326
        foreach ($MetaData->fieldNames as $value) {
327
            $fields[$value] = $accessor->getValue($helper, $value);
328
        }
329
330
        return new Response(
331
            $this->renderView(
332
                $configurator->getViewTemplate(),
333
                ['entity' => $helper, 'adminlistconfigurator' => $configurator, 'fields' => $fields]
334
            )
335
        );
336
    }
337
338
    /**
339
     * Delete the Entity using its ID
340
     *
341
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
342
     * @param int                           $entityId     The id to delete
343
     * @param Request|null                  $request
344
     *
345
     * @throws NotFoundHttpException
346
     * @throws AccessDeniedHttpException
347
     *
348
     * @return Response
349
     */
350
    protected function doDeleteAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
351
    {
352
        /* @var $em EntityManager */
353
        $em = $this->getEntityManager();
354
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
355
        if ($helper === null) {
356
            throw new NotFoundHttpException('Entity not found.');
357
        }
358
        if (!$configurator->canDelete($helper)) {
359
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
360
        }
361
362
        $indexUrl = $configurator->getIndexUrl();
363
        if ($request->isMethod('POST')) {
364
            $adminListEvent = new AdminListEvent($helper, $request);
365
            $this->container->get('event_dispatcher')->dispatch(
366
                AdminListEvents::PRE_DELETE,
367
                $adminListEvent
368
            );
369
370
            // Check if Response is given
371
            if ($adminListEvent->getResponse() instanceof Response) {
372
                return $adminListEvent->getResponse();
373
            }
374
375
            $em->remove($helper);
376
            $em->flush();
377
            $this->container->get('event_dispatcher')->dispatch(
378
                AdminListEvents::POST_DELETE,
379
                $adminListEvent
380
            );
381
382
            // Check if Response is given
383
            if ($adminListEvent->getResponse() instanceof Response) {
384
                return $adminListEvent->getResponse();
385
            }
386
        }
387
388
        return new RedirectResponse(
389
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : [])
390
        );
391
    }
392
393
    /**
394
     * Move an item up in the list.
395
     *
396
     * @return RedirectResponse
397
     */
398 View Code Duplication
    protected function doMoveUpAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
399
    {
400
        $em = $this->getEntityManager();
401
        $sortableField = $configurator->getSortableField();
402
403
        $repositoryName = $this->getAdminListRepositoryName($configurator);
404
405
        $repo = $em->getRepository($repositoryName);
406
        $item = $repo->find($entityId);
407
408
        $setter = 'set' . ucfirst($sortableField);
409
        $getter = 'get' . ucfirst($sortableField);
410
411
        $nextItem = $repo->createQueryBuilder('i')
412
            ->where('i.' . $sortableField . ' < :weight')
413
            ->setParameter('weight', $item->$getter())
414
            ->orderBy('i.' . $sortableField, 'DESC')
415
            ->setMaxResults(1)
416
            ->getQuery()
417
            ->getOneOrNullResult();
418
        if ($nextItem) {
419
            $nextItem->$setter($item->$getter());
420
            $em->persist($nextItem);
421
            $item->$setter($item->$getter() - 1);
422
423
            $em->persist($item);
424
            $em->flush();
425
        }
426
427
        $indexUrl = $configurator->getIndexUrl();
428
429
        return new RedirectResponse(
430
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : [])
431
        );
432
    }
433
434 View Code Duplication
    protected function doMoveDownAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
435
    {
436
        $em = $this->getEntityManager();
437
        $sortableField = $configurator->getSortableField();
438
439
        $repositoryName = $this->getAdminListRepositoryName($configurator);
440
441
        $repo = $em->getRepository($repositoryName);
442
        $item = $repo->find($entityId);
443
444
        $setter = 'set' . ucfirst($sortableField);
445
        $getter = 'get' . ucfirst($sortableField);
446
447
        $nextItem = $repo->createQueryBuilder('i')
448
            ->where('i.' . $sortableField . ' > :weight')
449
            ->setParameter('weight', $item->$getter())
450
            ->orderBy('i.' . $sortableField, 'ASC')
451
            ->setMaxResults(1)
452
            ->getQuery()
453
            ->getOneOrNullResult();
454
        if ($nextItem) {
455
            $nextItem->$setter($item->$getter());
456
            $em->persist($nextItem);
457
            $item->$setter($item->$getter() + 1);
458
459
            $em->persist($item);
460
            $em->flush();
461
        }
462
463
        $indexUrl = $configurator->getIndexUrl();
464
465
        return new RedirectResponse(
466
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : [])
467
        );
468
    }
469
470
    private function getMaxSortableField($repo, $sort)
471
    {
472
        $maxWeight = $repo->createQueryBuilder('i')
473
            ->select('max(i.' . $sort . ')')
474
            ->getQuery()
475
            ->getSingleScalarResult();
476
477
        return (int) $maxWeight;
478
    }
479
480
    /**
481
     * @return bool
482
     */
483
    protected function isLockableEntityLocked(LockableEntityInterface $entity)
484
    {
485
        /** @var EntityVersionLockService $entityVersionLockService */
486
        $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
487
488
        return $entityVersionLockService->isEntityBelowThreshold($entity) && $entityVersionLockService->isEntityLocked(
489
                $this->getUser(),
490
                $entity
491
            );
492
    }
493
494
    /**
495
     * Sets the sort weight on a new item. Can be overridden if a non-default sorting implementation is being used.
496
     *
497
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
498
     * @param $item
499
     *
500
     * @return mixed
501
     */
502
    protected function setSortWeightOnNewItem(AbstractAdminListConfigurator $configurator, $item)
503
    {
504
        if ($configurator instanceof SortableInterface) {
505
            $repo = $this->getEntityManager()->getRepository($configurator->getRepositoryName());
506
            $sort = $configurator->getSortableField();
507
            $weight = $this->getMaxSortableField($repo, $sort);
508
            $setter = 'set' . ucfirst($sort);
509
            $item->$setter($weight + 1);
510
        }
511
512
        return $item;
513
    }
514
515
    protected function buildSortableFieldActions(AbstractAdminListConfigurator $configurator)
516
    {
517
        // Check if Sortable interface is implemented
518
        if ($configurator instanceof SortableInterface) {
519 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
520
                return [
521
                    'path' => $configurator->getPathByConvention() . '_move_up',
522
                    'params' => ['id' => $item->getId()],
523
                ];
524
            };
525
526
            $action = new SimpleItemAction($route, 'arrow-up', 'kuma_admin_list.action.move_up');
527
            $configurator->addItemAction($action);
528
529 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
530
                return [
531
                    'path' => $configurator->getPathByConvention() . '_move_down',
532
                    'params' => ['id' => $item->getId()],
533
                ];
534
            };
535
536
            $action = new SimpleItemAction($route, 'arrow-down', 'kuma_admin_list.action.move_down');
537
            $configurator->addItemAction($action);
538
        }
539
    }
540
541
    /**
542
     * @return string
543
     */
544
    protected function getAdminListRepositoryName(AbstractAdminListConfigurator $configurator)
545
    {
546
        $em = $this->getEntityManager();
547
        $className = $em->getClassMetadata($configurator->getRepositoryName())->getName();
548
549
        $implements = class_implements($className);
550
        if (isset($implements[HasNodeInterface::class])) {
551
            return NodeTranslation::class;
552
        }
553
554
        return $configurator->getRepositoryName();
555
    }
556
}
557