Completed
Push — master ( 06c1ce...67d37c )
by Jeroen
06:20
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 null|Request                  $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 null|Request                  $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 null|Request                  $request
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 null|Request                  $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);
0 ignored issues
show
The method findOneById() does not exist on Doctrine\Common\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...
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 null|Request                  $request
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);
0 ignored issues
show
The method findOneById() does not exist on Doctrine\Common\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...
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