Completed
Push — master ( 1dbefb...c77374 )
by Jeroen
32s queued 11s
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\NodeBundle\Entity\HasNodeInterface;
18
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
19
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
20
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
21
use Symfony\Component\HttpFoundation\RedirectResponse;
22
use Kunstmaan\AdminListBundle\Service\EntityVersionLockService;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\HttpFoundation\Response;
25
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
26
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
27
use Symfony\Component\PropertyAccess\PropertyAccess;
28
29
/**
30
 * AdminListController
31
 */
32
abstract class AdminListController extends Controller
33
{
34
    /**
35
     * You can override this method to return the correct entity manager when using multiple databases ...
36
     *
37
     * @return \Doctrine\Common\Persistence\ObjectManager|object
38
     */
39
    protected function getEntityManager()
40
    {
41
        return $this->getDoctrine()->getManager();
42
    }
43
44
    /**
45
     * Shows the list of entities
46
     *
47
     * @param AbstractAdminListConfigurator $configurator
48
     * @param Request|null                  $request
49
     *
50
     * @return Response
51
     */
52
    protected function doIndexAction(AbstractAdminListConfigurator $configurator, Request $request)
53
    {
54
        /* @var AdminList $adminList */
55
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createList($configurator);
56
        $adminList->bindRequest($request);
57
58
        $this->buildSortableFieldActions($configurator);
59
60
        return new Response(
61
            $this->renderView(
62
                $configurator->getListTemplate(),
63
                array('adminlist' => $adminList, 'adminlistconfigurator' => $configurator, 'addparams' => array())
64
            )
65
        );
66
    }
67
68
    /**
69
     * Export a list of Entities
70
     *
71
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
72
     * @param string                        $_format      The format to export to
73
     * @param Request|null                  $request
74
     *
75
     * @throws AccessDeniedHttpException
76
     *
77
     * @return Response
78
     */
79
    protected function doExportAction(AbstractAdminListConfigurator $configurator, $_format, Request $request = null)
80
    {
81
        if (!$configurator->canExport()) {
82
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
83
        }
84
85
        /* @var AdminList $adminList */
86
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createExportList($configurator);
87
        $adminList->bindRequest($request);
88
89
        return $this->container->get('kunstmaan_adminlist.service.export')->getDownloadableResponse($adminList, $_format);
90
    }
91
92
    /**
93
     * Creates and processes the form to add a new Entity
94
     *
95
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
96
     * @param string                        $type         The type to add
97
     * @param Request|null                  $request
98
     *
99
     * @throws AccessDeniedHttpException
100
     *
101
     * @return Response
102
     */
103
    protected function doAddAction(AbstractAdminListConfigurator $configurator, $type = null, Request $request)
104
    {
105
        if (!$configurator->canAdd()) {
106
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
107
        }
108
109
        /* @var EntityManager $em */
110
        $em = $this->getEntityManager();
111
        $entityName = isset($type) ? $type : $configurator->getRepositoryName();
112
113
        $classMetaData = $em->getClassMetadata($entityName);
114
        // Creates a new instance of the mapped class, without invoking the constructor.
115
        $classname = $classMetaData->getName();
116
        $helper = new $classname();
117
        $helper = $configurator->decorateNewEntity($helper);
118
119
        $formType = $configurator->getAdminType($helper);
120
121
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
122
        $event = $this->dispatch($event, Events::ADAPT_SIMPLE_FORM);
123
        $tabPane = $event->getTabPane();
124
125
        $form = $this->createForm($formType, $helper, $event->getOptions());
126
127 View Code Duplication
        if ($request->isMethod('POST')) {
128
            if ($tabPane) {
129
                $tabPane->bindRequest($request);
130
                $form = $tabPane->getForm();
131
            } else {
132
                $form->handleRequest($request);
133
            }
134
135
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
136
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
137
                $adminListEvent = new AdminListEvent($helper, $request, $form);
138
                $this->dispatch(
139
                    $adminListEvent,
140
                    AdminListEvents::PRE_ADD
141
                );
142
143
                // Check if Response is given
144
                if ($adminListEvent->getResponse() instanceof Response) {
145
                    return $adminListEvent->getResponse();
146
                }
147
148
                // Set sort weight
149
                $helper = $this->setSortWeightOnNewItem($configurator, $helper);
150
151
                $em->persist($helper);
152
                $em->flush();
153
                $this->dispatch(
154
                    $adminListEvent,
155
                    AdminListEvents::POST_ADD
156
                );
157
158
                // Check if Response is given
159
                if ($adminListEvent->getResponse() instanceof Response) {
160
                    return $adminListEvent->getResponse();
161
                }
162
163
                $indexUrl = $configurator->getIndexUrl();
164
165
                return new RedirectResponse(
166
                    $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
167
                );
168
            }
169
        }
170
171
        $params = [
172
            'form' => $form->createView(),
173
            'adminlistconfigurator' => $configurator,
174
            'entityVersionLockCheck' => false,
175
            'entity' => $helper,
176
        ];
177
178
        if ($tabPane) {
179
            $params = array_merge($params, array('tabPane' => $tabPane));
180
        }
181
182
        return new Response(
183
            $this->renderView($configurator->getAddTemplate(), $params)
184
        );
185
    }
186
187
    /**
188
     * Creates and processes the edit form for an Entity using its ID
189
     *
190
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
191
     * @param string                        $entityId     The id of the entity that will be edited
192
     * @param Request|null                  $request
193
     *
194
     * @throws NotFoundHttpException
195
     * @throws AccessDeniedHttpException
196
     *
197
     * @return Response
198
     */
199
    protected function doEditAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
200
    {
201
        /* @var EntityManager $em */
202
        $em = $this->getEntityManager();
203
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
204
205
        if ($helper === null) {
206
            throw new NotFoundHttpException('Entity not found.');
207
        }
208
209
        if (!$configurator->canEdit($helper)) {
210
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
211
        }
212
213
        // This entity is locked
214
        if (($helper instanceof LockableEntityInterface) && $this->isLockableEntityLocked($helper)) {
215
            $indexUrl = $configurator->getIndexUrl();
216
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
217
            if (!$request->isXmlHttpRequest()) {
218
                /** @var EntityVersionLockService $entityVersionLockService */
219
                $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
220
221
                $user = $entityVersionLockService->getUsersWithEntityVersionLock($helper, $this->getUser());
222
                $message = $this->container->get('translator')->trans('kuma_admin_list.edit.flash.locked', array('%user%' => implode(', ', $user)));
223
                $this->addFlash(
224
                    FlashTypes::WARNING,
225
                    $message
226
                );
227
228
                return new RedirectResponse(
229
                    $this->generateUrl(
230
                        $indexUrl['path'],
231
                        isset($indexUrl['params']) ? $indexUrl['params'] : array()
232
                    )
233
                );
234
            }
235
        }
236
237
        $formType = $configurator->getAdminType($helper);
238
239
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
240
        $event = $this->dispatch($event, Events::ADAPT_SIMPLE_FORM);
241
        $tabPane = $event->getTabPane();
242
243
        $form = $this->createForm($formType, $helper, $event->getOptions());
244
245 View Code Duplication
        if ($request->isMethod('POST')) {
246
            if ($tabPane) {
247
                $tabPane->bindRequest($request);
248
                $form = $tabPane->getForm();
249
            } else {
250
                $form->handleRequest($request);
251
            }
252
253
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
254
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
255
                $adminListEvent = new AdminListEvent($helper, $request, $form);
256
                $this->dispatch(
257
                    $adminListEvent,
258
                    AdminListEvents::PRE_EDIT
259
                );
260
261
                // Check if Response is given
262
                if ($adminListEvent->getResponse() instanceof Response) {
263
                    return $adminListEvent->getResponse();
264
                }
265
266
                $em->persist($helper);
267
                $em->flush();
268
                $this->dispatch(
269
                    $adminListEvent,
270
                    AdminListEvents::POST_EDIT
271
                );
272
273
                // Check if Response is given
274
                if ($adminListEvent->getResponse() instanceof Response) {
275
                    return $adminListEvent->getResponse();
276
                }
277
278
                $indexUrl = $configurator->getIndexUrl();
279
280
                // Don't redirect to listing when coming from ajax request, needed for url chooser.
281
                if (!$request->isXmlHttpRequest()) {
282
                    return new RedirectResponse(
283
                        $this->generateUrl(
284
                            $indexUrl['path'],
285
                            isset($indexUrl['params']) ? $indexUrl['params'] : array()
286
                        )
287
                    );
288
                }
289
            }
290
        }
291
292
        $configurator->buildItemActions();
293
294
        $params = [
295
            'form' => $form->createView(),
296
            'entity' => $helper, 'adminlistconfigurator' => $configurator,
297
            'entityVersionLockInterval' => $this->container->getParameter('kunstmaan_entity.lock_check_interval'),
298
            'entityVersionLockCheck' => $this->container->getParameter('kunstmaan_entity.lock_enabled') && $helper instanceof LockableEntityInterface,
299
        ];
300
301
        if ($tabPane) {
302
            $params = array_merge($params, array('tabPane' => $tabPane));
303
        }
304
305
        return new Response(
306
            $this->renderView(
307
                $configurator->getEditTemplate(),
308
                $params
309
            )
310
        );
311
    }
312
313
    protected function doViewAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
314
    {
315
        /* @var EntityManager $em */
316
        $em = $this->getEntityManager();
317
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
318
        if ($helper === null) {
319
            throw new NotFoundHttpException('Entity not found.');
320
        }
321
322
        if (!$configurator->canView($helper)) {
323
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
324
        }
325
326
        $MetaData = $em->getClassMetadata($configurator->getRepositoryName());
327
        $fields = array();
328
        $accessor = PropertyAccess::createPropertyAccessor();
329
        foreach ($MetaData->fieldNames as $value) {
330
            $fields[$value] = $accessor->getValue($helper, $value);
331
        }
332
333
        return new Response(
334
            $this->renderView(
335
                $configurator->getViewTemplate(),
336
                array('entity' => $helper, 'adminlistconfigurator' => $configurator, 'fields' => $fields)
337
            )
338
        );
339
    }
340
341
    /**
342
     * Delete the Entity using its ID
343
     *
344
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
345
     * @param int                           $entityId     The id to delete
346
     * @param Request|null                  $request
347
     *
348
     * @throws NotFoundHttpException
349
     * @throws AccessDeniedHttpException
350
     *
351
     * @return Response
352
     */
353
    protected function doDeleteAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
354
    {
355
        /* @var $em EntityManager */
356
        $em = $this->getEntityManager();
357
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
358
        if ($helper === null) {
359
            throw new NotFoundHttpException('Entity not found.');
360
        }
361
        if (!$configurator->canDelete($helper)) {
362
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
363
        }
364
365
        $indexUrl = $configurator->getIndexUrl();
366
        if ($request->isMethod('POST')) {
367
            $adminListEvent = new AdminListEvent($helper, $request);
368
            $this->dispatch(
369
                $adminListEvent,
370
                AdminListEvents::PRE_DELETE
371
            );
372
373
            // Check if Response is given
374
            if ($adminListEvent->getResponse() instanceof Response) {
375
                return $adminListEvent->getResponse();
376
            }
377
378
            $em->remove($helper);
379
            $em->flush();
380
            $this->dispatch(
381
                $adminListEvent,
382
                AdminListEvents::POST_DELETE
383
            );
384
385
            // Check if Response is given
386
            if ($adminListEvent->getResponse() instanceof Response) {
387
                return $adminListEvent->getResponse();
388
            }
389
        }
390
391
        return new RedirectResponse(
392
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
393
        );
394
    }
395
396
    /**
397
     * Move an item up in the list.
398
     *
399
     * @return RedirectResponse
400
     */
401 View Code Duplication
    protected function doMoveUpAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
402
    {
403
        $em = $this->getEntityManager();
404
        $sortableField = $configurator->getSortableField();
405
406
        $repositoryName = $this->getAdminListRepositoryName($configurator);
407
408
        $repo = $em->getRepository($repositoryName);
409
        $item = $repo->find($entityId);
410
411
        $setter = 'set'.ucfirst($sortableField);
412
        $getter = 'get'.ucfirst($sortableField);
413
414
        $nextItem = $repo->createQueryBuilder('i')
415
            ->where('i.'.$sortableField.' < :weight')
416
            ->setParameter('weight', $item->$getter())
417
            ->orderBy('i.'.$sortableField, 'DESC')
418
            ->setMaxResults(1)
419
            ->getQuery()
420
            ->getOneOrNullResult();
421
        if ($nextItem) {
422
            $nextItem->$setter($item->$getter());
423
            $em->persist($nextItem);
424
            $item->$setter($item->$getter() - 1);
425
426
            $em->persist($item);
427
            $em->flush();
428
        }
429
430
        $indexUrl = $configurator->getIndexUrl();
431
432
        return new RedirectResponse(
433
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
434
        );
435
    }
436
437 View Code Duplication
    protected function doMoveDownAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
438
    {
439
        $em = $this->getEntityManager();
440
        $sortableField = $configurator->getSortableField();
441
442
        $repositoryName = $this->getAdminListRepositoryName($configurator);
443
444
        $repo = $em->getRepository($repositoryName);
445
        $item = $repo->find($entityId);
446
447
        $setter = 'set'.ucfirst($sortableField);
448
        $getter = 'get'.ucfirst($sortableField);
449
450
        $nextItem = $repo->createQueryBuilder('i')
451
            ->where('i.'.$sortableField.' > :weight')
452
            ->setParameter('weight', $item->$getter())
453
            ->orderBy('i.'.$sortableField, 'ASC')
454
            ->setMaxResults(1)
455
            ->getQuery()
456
            ->getOneOrNullResult();
457
        if ($nextItem) {
458
            $nextItem->$setter($item->$getter());
459
            $em->persist($nextItem);
460
            $item->$setter($item->$getter() + 1);
461
462
            $em->persist($item);
463
            $em->flush();
464
        }
465
466
        $indexUrl = $configurator->getIndexUrl();
467
468
        return new RedirectResponse(
469
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
470
        );
471
    }
472
473
    private function getMaxSortableField($repo, $sort)
474
    {
475
        $maxWeight = $repo->createQueryBuilder('i')
476
            ->select('max(i.'.$sort.')')
477
            ->getQuery()
478
            ->getSingleScalarResult();
479
480
        return (int) $maxWeight;
481
    }
482
483
    /**
484
     * @param LockableEntityInterface $entity
485
     *
486
     * @return bool
487
     */
488
    protected function isLockableEntityLocked(LockableEntityInterface $entity)
489
    {
490
        /** @var EntityVersionLockService $entityVersionLockService */
491
        $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
492
493
        return $entityVersionLockService->isEntityBelowThreshold($entity) && $entityVersionLockService->isEntityLocked(
494
                $this->getUser(),
495
                $entity
496
            );
497
    }
498
499
    /**
500
     * Sets the sort weight on a new item. Can be overridden if a non-default sorting implementation is being used.
501
     *
502
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
503
     * @param $item
504
     *
505
     * @return mixed
506
     */
507
    protected function setSortWeightOnNewItem(AbstractAdminListConfigurator $configurator, $item)
508
    {
509
        if ($configurator instanceof SortableInterface) {
510
            $repo = $this->getEntityManager()->getRepository($configurator->getRepositoryName());
511
            $sort = $configurator->getSortableField();
512
            $weight = $this->getMaxSortableField($repo, $sort);
513
            $setter = 'set'.ucfirst($sort);
514
            $item->$setter($weight + 1);
515
        }
516
517
        return $item;
518
    }
519
520
    protected function buildSortableFieldActions(AbstractAdminListConfigurator $configurator)
521
    {
522
        // Check if Sortable interface is implemented
523
        if ($configurator instanceof SortableInterface) {
524 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
525
                return array(
526
                    'path' => $configurator->getPathByConvention().'_move_up',
527
                    'params' => array('id' => $item->getId()),
528
                );
529
            };
530
531
            $action = new SimpleItemAction($route, 'arrow-up', 'kuma_admin_list.action.move_up');
532
            $configurator->addItemAction($action);
533
534 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
535
                return array(
536
                    'path' => $configurator->getPathByConvention().'_move_down',
537
                    'params' => array('id' => $item->getId()),
538
                );
539
            };
540
541
            $action = new SimpleItemAction($route, 'arrow-down', 'kuma_admin_list.action.move_down');
542
            $configurator->addItemAction($action);
543
        }
544
    }
545
546
    /**
547
     * @param AbstractAdminListConfigurator $configurator
548
     *
549
     * @return string
550
     */
551
    protected function getAdminListRepositoryName(AbstractAdminListConfigurator $configurator)
552
    {
553
        $em = $this->getEntityManager();
554
        $className = $em->getClassMetadata($configurator->getRepositoryName())->getName();
555
556
        $implements = class_implements($className);
557
        if (isset($implements[HasNodeInterface::class])) {
558
            return NodeTranslation::class;
559
        }
560
561
        return $configurator->getRepositoryName();
562
    }
563
564
    /**
565
     * @param object $event
566
     * @param string $eventName
567
     *
568
     * @return object
569
     */
570 View Code Duplication
    private function dispatch($event, string $eventName)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
571
    {
572
        $eventDispatcher = $this->container->get('event_dispatcher');
573
        if (class_exists(LegacyEventDispatcherProxy::class)) {
574
            $eventDispatcher = LegacyEventDispatcherProxy::decorate($eventDispatcher);
575
576
            return $eventDispatcher->dispatch($event, $eventName);
577
        }
578
579
        return $eventDispatcher->dispatch($eventName, $event);
580
    }
581
}
582