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

AdminListBundle/Controller/AdminListController.php (3 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
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);
0 ignored issues
show
It seems like $item defined by $repo->find($entityId) on line 414 can also be of type null; however, Doctrine\Common\Persiste...bjectManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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);
0 ignored issues
show
It seems like $item defined by $repo->find($entityId) on line 450 can also be of type null; however, Doctrine\Common\Persiste...bjectManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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