Completed
Push — 5.3 ( 958546...1cc96e )
by Jeroen
14:02 queued 07:05
created

AdminListBundle/Controller/AdminListController.php (1 issue)

Checks whether return doc types can be made more specific.

Documentation Informational

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
0 ignored issues
show
Consider making the return type a bit more specific; maybe use \Doctrine\Common\Persistence\ObjectManager.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

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