Completed
Push — master ( ae5e03...0447ee )
by Jeroen
10:35 queued 04:37
created

AdminListBundle/Controller/AdminListController.php (2 issues)

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