Issues (3627)

Controller/AbstractStandardFormController.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2016 Mautic Contributors. All rights reserved
5
 * @author      Mautic, Inc.
6
 *
7
 * @link        https://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CoreBundle\Controller;
13
14
use Mautic\CoreBundle\Form\Type\DateRangeType;
15
use Mautic\CoreBundle\Model\AbstractCommonModel;
16
use Mautic\CoreBundle\Model\FormModel;
17
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
18
use Symfony\Component\Form\Form;
19
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20
21
abstract class AbstractStandardFormController extends AbstractFormController
22
{
23
    use FormErrorMessagesTrait;
24
25
    /**
26
     * Get this controller's model name.
27
     */
28
    abstract protected function getModelName();
29
30
    /**
31
     * Support non-index pages such as modal forms.
32
     *
33
     * @param string $route
34
     * @param array  $parameters
35
     * @param int    $referenceType
36
     *
37
     * @return bool|string
38
     */
39
    public function generateUrl($route, $parameters = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
40
    {
41
        if (false === $route) {
42
            return false;
43
        }
44
45
        return parent::generateUrl($route, $parameters, $referenceType);
46
    }
47
48
    /**
49
     * Modify the cloned entity prior to sending through editAction.
50
     *
51
     * @param $newEntity
52
     * @param $entity
53
     *
54
     * @return array of arguments for editAction
55
     */
56
    protected function afterEntityClone($newEntity, $entity)
57
    {
58
        return [$newEntity, true];
59
    }
60
61
    /**
62
     * Called after the entity has been persisted allowing for custom preperation of $entity prior to viewAction.
63
     *
64
     * @param      $entity
65
     * @param      $action
66
     * @param null $pass
67
     */
68
    protected function afterEntitySave($entity, Form $form, $action, $pass = null)
69
    {
70
    }
71
72
    /**
73
     * Called after the form is validated on POST.
74
     *
75
     * @param $isValid
76
     * @param $entity
77
     * @param $action
78
     * @param $isClone
79
     */
80
    protected function afterFormProcessed($isValid, $entity, Form $form, $action, $isClone = false)
81
    {
82
    }
83
84
    /**
85
     * Deletes a group of entities.
86
     *
87
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
88
     */
89
    protected function batchDeleteStandard()
90
    {
91
        $page      = $this->get('session')->get('mautic.'.$this->getSessionBase().'.page', 1);
92
        $returnUrl = $this->generateUrl($this->getIndexRoute(), ['page' => $page]);
93
        $flashes   = [];
94
95
        $postActionVars = [
96
            'returnUrl'       => $returnUrl,
97
            'viewParameters'  => ['page' => $page],
98
            'contentTemplate' => $this->getControllerBase().':'.$this->getPostActionControllerAction('batchDelete'),
99
            'passthroughVars' => [
100
                'mauticContent' => $this->getJsLoadMethodPrefix(),
101
            ],
102
        ];
103
104
        if ('POST' == $this->request->getMethod()) {
105
            $model     = $this->getModel($this->getModelName());
106
            $ids       = json_decode($this->request->query->get('ids', ''));
107
            $deleteIds = [];
108
109
            // Loop over the IDs to perform access checks pre-delete
110
            foreach ($ids as $objectId) {
111
                $entity = $model->getEntity($objectId);
112
113
                if (null === $entity) {
114
                    $flashes[] = [
115
                        'type'    => 'error',
116
                        'msg'     => $this->getTranslatedString('error.notfound'),
117
                        'msgVars' => ['%id%' => $objectId],
118
                    ];
119
                } elseif (!$this->checkActionPermission('batchDelete', $entity)) {
120
                    $flashes[] = $this->accessDenied(true);
121
                } elseif ($model->isLocked($entity)) {
122
                    $flashes[] = $this->isLocked($postActionVars, $entity, $this->getModelName(), true);
123
                } else {
124
                    $deleteIds[] = $objectId;
125
                }
126
            }
127
128
            // Delete everything we are able to
129
            if (!empty($deleteIds)) {
130
                $entities = $model->deleteEntities($deleteIds);
131
132
                $flashes[] = [
133
                    'type'    => 'notice',
134
                    'msg'     => $this->getTranslatedString('notice.batch_deleted'),
135
                    'msgVars' => [
136
                        '%count%' => count($entities),
137
                    ],
138
                ];
139
            }
140
        } //else don't do anything
141
142
        return $this->postActionRedirect(
143
            $this->getPostActionRedirectArguments(
144
                array_merge(
145
                    $postActionVars,
146
                    [
147
                        'flashes' => $flashes,
148
                    ]
149
                ),
150
                'batchDelete'
151
            )
152
        );
153
    }
154
155
    /**
156
     * Modify entity prior to persisting or perform custom validation on the form.
157
     *
158
     * @param $entity
159
     * @param $form
160
     * @param $action
161
     * @param $objectId
162
     * @param $isClone
163
     *
164
     * @return mixed Whatever is returned will be passed into afterEntitySave; pass false to fail validation
165
     */
166
    protected function beforeEntitySave($entity, Form $form, $action, $objectId = null, $isClone = false)
167
    {
168
        return true;
169
    }
170
171
    /**
172
     * Do anything necessary before the form is checked for POST and processed.
173
     *
174
     * @param $entity
175
     * @param $action
176
     * @param $isPost
177
     * @param $objectId
178
     * @param $isClone
179
     */
180
    protected function beforeFormProcessed($entity, Form $form, $action, $isPost, $objectId = null, $isClone = false)
181
    {
182
    }
183
184
    /**
185
     * @param      $action
186
     * @param null $entity
187
     * @param null $objectId
188
     *
189
     * @return bool|mixed
190
     */
191
    protected function checkActionPermission($action, $entity = null, $objectId = null)
192
    {
193
        /** @var CorePermissions $security */
194
        $security = $this->get('mautic.security');
195
196
        $permissionUser = 0;
197
198
        if ($entity) {
199
            $permissionUser = method_exists($entity, 'getPermissionUser') ? $entity->getPermissionUser() : $entity->getCreatedBy();
200
        }
201
202
        if ($entity) {
203
            switch ($action) {
204
                case 'new':
205
                    return $security->isGranted($this->getPermissionBase().':create');
206
                case 'view':
207
                case 'index':
208
                    return ($entity) ? $security->hasEntityAccess(
209
                        $this->getPermissionBase().':viewown',
210
                        $this->getPermissionBase().':viewother',
211
                        $permissionUser
212
                    ) : $security->isGranted($this->getPermissionBase().':view');
213
                case 'clone':
214
                    return
215
                        $security->isGranted($this->getPermissionBase().':create')
216
                        && $this->get('mautic.security')->hasEntityAccess(
217
                            $this->getPermissionBase().':viewown',
218
                            $this->getPermissionBase().':viewother',
219
                            $permissionUser
220
                        );
221
                case 'delete':
222
                case 'batchDelete':
223
                    return $this->get('mautic.security')->hasEntityAccess(
224
                        $this->getPermissionBase().':deleteown',
225
                        $this->getPermissionBase().':deleteother',
226
                        $permissionUser
227
                    );
228
                default:
229
                    return $this->get('mautic.security')->hasEntityAccess(
230
                        $this->getPermissionBase().':'.$action.'own',
231
                        $this->getPermissionBase().':'.$action.'other',
232
                        $permissionUser
233
                    );
234
            }
235
        } else {
236
            switch ($action) {
237
                case 'new':
238
                    return $security->isGranted($this->getPermissionBase().':create');
239
                case 'view':
240
                case 'index':
241
                    return $security->isGranted($this->getPermissionBase().':view');
242
                case 'clone':
243
                    return
244
                        $security->isGranted($this->getPermissionBase().':create')
245
                        && $security->isGranted($this->getPermissionBase().':view');
246
                case 'delete':
247
                case 'batchDelete':
248
                    return $security->isGranted($this->getPermissionBase().':delete');
249
                default:
250
                    return $security->isGranted($this->getPermissionBase().':'.$action);
251
            }
252
        }
253
254
        return false;
255
    }
256
257
    /**
258
     * Clone an entity.
259
     *
260
     * @param $objectId
261
     *
262
     * @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
263
     */
264
    protected function cloneStandard($objectId)
265
    {
266
        $model  = $this->getModel($this->getModelName());
267
        $entity = $model->getEntity($objectId);
268
269
        if (null != $entity) {
270
            if (!$this->checkActionPermission('clone', $entity)) {
271
                return $this->accessDenied();
272
            }
273
274
            $newEntity = clone $entity;
275
276
            if ($arguments = $this->afterEntityClone($newEntity, $entity)) {
277
                return call_user_func_array([$this, 'editAction'], $arguments);
278
            } else {
279
                return $this->editAction($newEntity, true);
280
            }
281
        }
282
283
        return $this->newAction();
284
    }
285
286
    /**
287
     * Deletes the entity.
288
     *
289
     * @param int $objectId
290
     *
291
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
292
     */
293
    protected function deleteStandard($objectId)
294
    {
295
        $page      = $this->get('session')->get('mautic.'.$this->getSessionBase().'.page', 1);
296
        $returnUrl = $this->generateUrl($this->getIndexRoute(), ['page' => $page]);
297
        $flashes   = [];
298
        $model     = $this->getModel($this->getModelName());
299
        $entity    = $model->getEntity($objectId);
300
301
        $postActionVars = [
302
            'returnUrl'       => $returnUrl,
303
            'viewParameters'  => ['page' => $page],
304
            'contentTemplate' => $this->getControllerBase().':'.$this->getPostActionControllerAction('delete'),
305
            'passthroughVars' => [
306
                'mauticContent' => $this->getJsLoadMethodPrefix(),
307
            ],
308
            'entity' => $entity,
309
        ];
310
311
        if ('POST' == $this->request->getMethod()) {
312
            if (null === $entity) {
313
                $flashes[] = [
314
                    'type'    => 'error',
315
                    'msg'     => $this->getTranslatedString('error.notfound'),
316
                    'msgVars' => ['%id%' => $objectId],
317
                ];
318
            } elseif (!$this->checkActionPermission('delete', $entity)) {
319
                return $this->accessDenied();
320
            } elseif ($model->isLocked($entity)) {
321
                return $this->isLocked($postActionVars, $entity, $this->getModelName());
322
            }
323
324
            $model->deleteEntity($entity);
325
326
            $identifier = $this->get('translator')->trans($entity->getName());
327
            $flashes[]  = [
328
                'type'    => 'notice',
329
                'msg'     => 'mautic.core.notice.deleted',
330
                'msgVars' => [
331
                    '%name%' => $identifier,
332
                    '%id%'   => $objectId,
333
                ],
334
            ];
335
        } //else don't do anything
336
337
        return $this->postActionRedirect(
338
            $this->getPostActionRedirectArguments(
339
                array_merge(
340
                    $postActionVars,
341
                    [
342
                        'flashes' => $flashes,
343
                    ]
344
                ),
345
                'delete'
346
            )
347
        );
348
    }
349
350
    /**
351
     * @param      $objectId
352
     * @param bool $ignorePost
353
     *
354
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
355
     *
356
     * @throws \Exception
357
     */
358
    protected function editStandard($objectId, $ignorePost = false)
359
    {
360
        $isClone = false;
361
        $model   = $this->getModel($this->getModelName());
362
        if (!$model instanceof FormModel) {
363
            throw new \Exception(get_class($model).' must extend '.FormModel::class);
364
        }
365
366
        $entity = $this->getFormEntity('edit', $objectId, $isClone);
367
368
        //set the return URL
369
        $returnUrl      = $this->generateUrl($this->getIndexRoute());
370
        $page           = $this->get('session')->get('mautic.'.$this->getSessionBase().'.page', 1);
371
        $viewParameters = ['page' => $page];
372
373
        $template = $this->getControllerBase().':'.$this->getPostActionControllerAction('edit');
374
375
        $postActionVars = [
376
            'returnUrl'       => $returnUrl,
377
            'viewParameters'  => $viewParameters,
378
            'contentTemplate' => $template,
379
            'passthroughVars' => [
380
                'mauticContent' => $this->getJsLoadMethodPrefix(),
381
            ],
382
            'entity' => $entity,
383
        ];
384
385
        //form not found
386
        if (null === $entity) {
387
            return $this->postActionRedirect(
388
                $this->getPostActionRedirectArguments(
389
                    array_merge(
390
                        $postActionVars,
391
                        [
392
                            'flashes' => [
393
                                [
394
                                    'type'    => 'error',
395
                                    'msg'     => $this->getTranslatedString('error.notfound'),
396
                                    'msgVars' => ['%id%' => $objectId],
397
                                ],
398
                            ],
399
                        ]
400
                    ),
401
                    'edit'
402
                )
403
            );
404
        } elseif ((!$isClone && !$this->checkActionPermission('edit', $entity)) || ($isClone && !$this->checkActionPermission('create'))) {
405
            //deny access if the entity is not a clone and don't have permission to edit or is a clone and don't have permission to create
406
            return $this->accessDenied();
407
        } elseif (!$isClone && $model->isLocked($entity)) {
408
            //deny access if the entity is locked
409
            return $this->isLocked($postActionVars, $entity, $this->getModelName());
410
        }
411
412
        $options = $this->getEntityFormOptions();
413
        $action  = $this->generateUrl($this->getActionRoute(), ['objectAction' => 'edit', 'objectId' => $objectId]);
414
        $form    = $model->createForm($entity, $this->get('form.factory'), $action, $options);
415
416
        $isPost = !$ignorePost && 'POST' == $this->request->getMethod();
417
        $this->beforeFormProcessed($entity, $form, 'edit', $isPost, $objectId, $isClone);
418
419
        ///Check for a submitted form and process it
420
        if ($isPost) {
421
            $valid = false;
422
            if (!$cancelled = $this->isFormCancelled($form)) {
423
                if ($valid = $this->isFormValid($form)) {
424
                    if ($valid = $this->beforeEntitySave($entity, $form, 'edit', $objectId, $isClone)) {
425
                        $model->saveEntity($entity, $form->get('buttons')->get('save')->isClicked());
426
427
                        $this->afterEntitySave($entity, $form, 'edit', $valid);
428
429
                        $this->addFlash(
430
                            'mautic.core.notice.updated',
431
                            [
432
                                '%name%'      => $entity->getName(),
433
                                '%menu_link%' => $this->getIndexRoute(),
434
                                '%url%'       => $this->generateUrl(
435
                                    $this->getActionRoute(),
436
                                    [
437
                                        'objectAction' => 'edit',
438
                                        'objectId'     => $entity->getId(),
439
                                    ]
440
                                ),
441
                            ]
442
                        );
443
444
                        if ($entity->getId() !== $objectId) {
445
                            // No longer a clone - this is important for Apply
446
                            $objectId = $entity->getId();
447
                        }
448
449
                        if (!$this->isFormApplied($form) && method_exists($this, 'viewAction')) {
450
                            $viewParameters                    = ['objectId' => $objectId, 'objectAction' => 'view'];
451
                            $returnUrl                         = $this->generateUrl($this->getActionRoute(), $viewParameters);
452
                            $postActionVars['contentTemplate'] = $this->getControllerBase().':view';
453
                        }
454
                    }
455
456
                    $this->afterFormProcessed($valid, $entity, $form, 'edit', $isClone);
457
                }
458
            } else {
459
                if (!$isClone) {
460
                    //unlock the entity
461
                    $model->unlockEntity($entity);
462
                }
463
464
                $returnUrl = $this->generateUrl($this->getIndexRoute(), $viewParameters);
465
            }
466
467
            if ($cancelled || ($valid && !$this->isFormApplied($form))) {
468
                return $this->postActionRedirect(
469
                    $this->getPostActionRedirectArguments(
470
                        array_merge(
471
                            $postActionVars,
472
                            [
473
                                'returnUrl'      => $returnUrl,
474
                                'viewParameters' => $viewParameters,
475
                            ]
476
                        ),
477
                        'edit'
478
                    )
479
                );
480
            } elseif ($valid) {
481
                // Rebuild the form with new action so that apply doesn't keep creating a clone
482
                $action = $this->generateUrl($this->getActionRoute(), ['objectAction' => 'edit', 'objectId' => $entity->getId()]);
483
                $form   = $model->createForm($entity, $this->get('form.factory'), $action);
484
                $this->beforeFormProcessed($entity, $form, 'edit', false, $isClone);
485
            }
486
        } elseif (!$isClone) {
487
            $model->lockEntity($entity);
488
        }
489
490
        $delegateArgs = [
491
            'viewParameters' => [
492
                'permissionBase'  => $this->getPermissionBase(),
493
                'mauticContent'   => $this->getJsLoadMethodPrefix(),
494
                'actionRoute'     => $this->getActionRoute(),
495
                'indexRoute'      => $this->getIndexRoute(),
496
                'tablePrefix'     => $model->getRepository()->getTableAlias(),
497
                'modelName'       => $this->getModelName(),
498
                'translationBase' => $this->getTranslationBase(),
499
                'tmpl'            => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
500
                'entity'          => $entity,
501
                'form'            => $this->getFormView($form, 'edit'),
502
            ],
503
            'contentTemplate' => $this->getTemplateName('form.html.php'),
504
            'passthroughVars' => [
505
                'mauticContent' => $this->getJsLoadMethodPrefix(),
506
                'route'         => $this->generateUrl(
507
                    $this->getActionRoute(),
508
                    [
509
                        'objectAction' => 'edit',
510
                        'objectId'     => $entity->getId(),
511
                    ]
512
                ),
513
                'validationError' => $this->getFormErrorForBuilder($form),
514
            ],
515
            'objectId' => $objectId,
516
            'entity'   => $entity,
517
        ];
518
519
        return $this->delegateView(
520
            $this->getViewArguments($delegateArgs, 'edit')
521
        );
522
    }
523
524
    /**
525
     * Get action route.
526
     *
527
     * @return string
528
     */
529
    protected function getActionRoute()
530
    {
531
        return 'mautic_'.str_replace('mautic_', '', $this->getRouteBase().'_action');
532
    }
533
534
    /**
535
     * Get controller base if different than MauticCoreBundle:Standard.
536
     *
537
     * @return string
538
     */
539
    protected function getControllerBase()
540
    {
541
        return 'MauticCoreBundle:Standard';
542
    }
543
544
    /**
545
     * @param      $objectId
546
     * @param      $action
547
     * @param bool $isClone
548
     */
549
    protected function getFormEntity($action, &$objectId = null, &$isClone = false)
550
    {
551
        $model = $this->getModel($this->getModelName());
552
553
        switch ($action) {
554
            case 'new':
555
                $entity = $model->getEntity();
556
                break;
557
            case 'edit':
558
                /* @var $entity FormEntity */
559
                if (is_object($objectId)) {
560
                    $entity   = $objectId;
561
                    $isClone  = true;
562
                    $objectId = (!empty($this->sessionId)) ? $this->sessionId : 'mautic_'.sha1(uniqid(mt_rand(), true));
563
                } elseif (false !== strpos($objectId, 'mautic_')) {
564
                    $isClone = true;
565
                    $entity  = $model->getEntity();
566
                } else {
567
                    $entity = $model->getEntity($objectId);
568
                }
569
                break;
570
        }
571
572
        return $entity;
573
    }
574
575
    /**
576
     * Set custom form themes, etc.
577
     *
578
     * @param $action
579
     *
580
     * @return \Symfony\Component\Form\FormView
581
     */
582
    protected function getFormView(Form $form, $action)
583
    {
584
        return $form->createView();
585
    }
586
587
    /**
588
     * Get items for index list.
589
     *
590
     * @param $start
591
     * @param $limit
592
     * @param $filter
593
     * @param $orderBy
594
     * @param $orderByDir
595
     * @param $args
596
     */
597
    protected function getIndexItems($start, $limit, $filter, $orderBy, $orderByDir, array $args = [])
598
    {
599
        $items = $this->getModel($this->getModelName())->getEntities(
600
            array_merge(
601
                [
602
                    'start'      => $start,
603
                    'limit'      => $limit,
604
                    'filter'     => $filter,
605
                    'orderBy'    => $orderBy,
606
                    'orderByDir' => $orderByDir,
607
                ],
608
                $args
609
            )
610
        );
611
612
        $count = count($items);
613
614
        return [$count, $items];
615
    }
616
617
    /**
618
     * Get index route.
619
     *
620
     * @return string
621
     */
622
    protected function getIndexRoute()
623
    {
624
        return 'mautic_'.str_replace('mautic_', '', $this->getRouteBase().'_index');
625
    }
626
627
    /**
628
     * Get the name of the JS onLoad and onUnload methods for ajax.
629
     *
630
     * @return mixed
631
     */
632
    protected function getJsLoadMethodPrefix()
633
    {
634
        return $this->getModelName();
635
    }
636
637
    /**
638
     * Get the permission base from the model.
639
     *
640
     * @return string
641
     */
642
    protected function getPermissionBase()
643
    {
644
        return $this->getModel($this->getModelName())->getPermissionBase();
645
    }
646
647
    /**
648
     * Amend the parameters sent through postActionRedirect.
649
     *
650
     * @param $action
651
     *
652
     * @return array
653
     */
654
    protected function getPostActionRedirectArguments(array $args, $action)
655
    {
656
        return $args;
657
    }
658
659
    /**
660
     * @param $action
661
     *
662
     * @return string
663
     */
664
    protected function getPostActionControllerAction($action)
665
    {
666
        return 'index';
667
    }
668
669
    /**
670
     * Get the route base for getIndexRoute() and getActionRoute() if they do not meet the mautic_*_index and mautic_*_action standards.
671
     *
672
     * @return mixed
673
     */
674
    protected function getRouteBase()
675
    {
676
        return $this->getModelName();
677
    }
678
679
    /**
680
     * Provide the name of the column which is used for default ordering.
681
     *
682
     * @return string
683
     */
684
    protected function getDefaultOrderColumn()
685
    {
686
        return 'name';
687
    }
688
689
    /**
690
     * Provide the direction for default ordering.
691
     *
692
     * @return string
693
     */
694
    protected function getDefaultOrderDirection()
695
    {
696
        return 'ASC';
697
    }
698
699
    /**
700
     * @param null $objectId
701
     *
702
     * @return mixed
703
     */
704
    protected function getSessionBase($objectId = null)
705
    {
706
        $base = $this->getModelName();
707
708
        if (null !== $objectId) {
709
            $base .= '.'.$objectId;
710
        }
711
712
        return $base;
713
    }
714
715
    /**
716
     * Get template base different than MauticCoreBundle:Standard.
717
     *
718
     * @return string
719
     */
720
    protected function getTemplateBase()
721
    {
722
        return 'MauticCoreBundle:Standard';
723
    }
724
725
    /**
726
     * Get the template file.
727
     *
728
     * @param $file
729
     *
730
     * @return string
731
     */
732
    protected function getTemplateName($file)
733
    {
734
        if ($this->get('templating')->exists($this->getControllerBase().':'.$file)) {
735
            return $this->getControllerBase().':'.$file;
736
        } elseif ($this->get('templating')->exists($this->getTemplateBase().':'.$file)) {
737
            return $this->getTemplateBase().':'.$file;
738
        } else {
739
            return 'MauticCoreBundle:Standard:'.$file;
740
        }
741
    }
742
743
    /**
744
     * Get custom or core translation.
745
     *
746
     * @param $string
747
     *
748
     * @return string
749
     */
750
    protected function getTranslatedString($string)
751
    {
752
        return $this->get('translator')->hasId($this->getTranslationBase().'.'.$string) ? $this->getTranslationBase()
753
            .'.'.$string : 'mautic.core.'.$string;
754
    }
755
756
    /**
757
     * Get the base to override core translation keys.
758
     *
759
     * @return string
760
     */
761
    protected function getTranslationBase()
762
    {
763
        return 'mautic.'.$this->getModelName();
764
    }
765
766
    /**
767
     * Amend the parameters sent through delegateView.
768
     *
769
     * @param $action
770
     *
771
     * @return array
772
     */
773
    protected function getViewArguments(array $args, $action)
774
    {
775
        return $args;
776
    }
777
778
    /**
779
     * Return array of options for the form when it's being created.
780
     *
781
     * @return array
782
     */
783
    protected function getEntityFormOptions()
784
    {
785
        return [];
786
    }
787
788
    /**
789
     * Return array of options update select response.
790
     *
791
     * @param string $updateSelect HTML id of the select
792
     * @param object $entity
793
     * @param string $nameMethod   name of the entity method holding the name
794
     * @param string $groupMethod  name of the entity method holding the select group
795
     *
796
     * @return array
797
     */
798
    protected function getUpdateSelectParams($updateSelect, $entity, $nameMethod = 'getName', $groupMethod = 'getLanguage')
799
    {
800
        $options = [
801
            'updateSelect' => $updateSelect,
802
            'id'           => $entity->getId(),
803
            'name'         => $entity->$nameMethod(),
804
        ];
805
806
        if ($groupMethod) {
807
            $options['group'] = $entity->$groupMethod();
808
        }
809
810
        return $options;
811
    }
812
813
    /**
814
     * @param        $objectId
815
     * @param        $returnUrl
816
     * @param string $timezone
817
     * @param null   $dateRangeForm
818
     *
819
     * @return array
820
     */
821
    protected function getViewDateRange($objectId, $returnUrl, $timezone = 'local', &$dateRangeForm = null)
822
    {
823
        $name            = $this->getSessionBase($objectId).'.view.daterange';
824
        $method          = ('POST' === $this->request->getMethod()) ? 'request' : 'query';
825
        $dateRangeValues = $this->request->$method->get('daterange', $this->get('session')->get($name, []));
826
        $this->get('session')->set($name, $dateRangeValues);
827
828
        $dateRangeForm = $this->get('form.factory')->create(DateRangeType::class, $dateRangeValues, ['action' => $returnUrl]);
829
        $dateFrom      = new \DateTime($dateRangeForm['date_from']->getData());
830
        $dateFrom->setTime(0, 0, 0);
831
        $dateTo = new \DateTime($dateRangeForm['date_to']->getData());
832
        $dateTo->setTime(24, 59, 59);
833
834
        if ('utc' === $timezone) {
835
            $dateFrom = clone $dateFrom;
836
            $dateFrom->setTimezone(new \DateTimeZone('utc'));
837
            $dateTo = clone $dateTo;
838
            $dateTo->setTimezone(new \DateTimeZone('utc'));
839
        }
840
841
        return [$dateFrom, $dateTo];
842
    }
843
844
    /**
845
     * @param int $page
846
     *
847
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
848
     */
849
    protected function indexStandard($page = null)
850
    {
851
        //set some permissions
852
        $permissions = $this->get('mautic.security')->isGranted(
853
            [
854
                $this->getPermissionBase().':view',
855
                $this->getPermissionBase().':viewown',
856
                $this->getPermissionBase().':viewother',
857
                $this->getPermissionBase().':create',
858
                $this->getPermissionBase().':edit',
859
                $this->getPermissionBase().':editown',
860
                $this->getPermissionBase().':editother',
861
                $this->getPermissionBase().':delete',
862
                $this->getPermissionBase().':deleteown',
863
                $this->getPermissionBase().':deleteother',
864
                $this->getPermissionBase().':publish',
865
                $this->getPermissionBase().':publishown',
866
                $this->getPermissionBase().':publishother',
867
            ],
868
            'RETURN_ARRAY',
869
            null,
870
            true
871
        );
872
873
        if (!$this->checkActionPermission('index')) {
874
            return $this->accessDenied();
875
        }
876
877
        $this->setListFilters();
878
879
        $session = $this->get('session');
880
        if (empty($page)) {
881
            $page = $session->get('mautic.'.$this->getSessionBase().'.page', 1);
882
        }
883
884
        //set limits
885
        $limit = $session->get('mautic.'.$this->getSessionBase().'.limit', $this->coreParametersHelper->get('default_pagelimit'));
886
        $start = (1 === $page) ? 0 : (($page - 1) * $limit);
887
        if ($start < 0) {
888
            $start = 0;
889
        }
890
891
        $search = $this->request->get('search', $session->get('mautic.'.$this->getSessionBase().'.filter', ''));
892
        $session->set('mautic.'.$this->getSessionBase().'.filter', $search);
893
894
        $filter = ['string' => $search, 'force' => []];
895
896
        $model = $this->getModel($this->getModelName());
897
        $repo  = $model->getRepository();
898
899
        if (!$permissions[$this->getPermissionBase().':viewother']) {
900
            $filter['force'][] = ['column' => $repo->getTableAlias().'.createdBy', 'expr' => 'eq', 'value' => $this->user->getId()];
901
        }
902
903
        $orderBy    = $session->get('mautic.'.$this->getSessionBase().'.orderby', $repo->getTableAlias().'.'.$this->getDefaultOrderColumn());
904
        $orderByDir = $session->get('mautic.'.$this->getSessionBase().'.orderbydir', $this->getDefaultOrderDirection());
905
906
        list($count, $items) = $this->getIndexItems($start, $limit, $filter, $orderBy, $orderByDir);
907
908
        if ($count && $count < ($start + 1)) {
909
            //the number of entities are now less then the current page so redirect to the last page
910
            $lastPage = (1 === $count) ? 1 : (((ceil($count / $limit)) ?: 1) ?: 1);
911
912
            $session->set('mautic.'.$this->getSessionBase().'.page', $lastPage);
913
            $returnUrl = $this->generateUrl($this->getIndexRoute(), ['page' => $lastPage]);
914
915
            return $this->postActionRedirect(
916
                $this->getPostActionRedirectArguments(
917
                    [
918
                        'returnUrl'       => $returnUrl,
919
                        'viewParameters'  => ['page' => $lastPage],
920
                        'contentTemplate' => $this->getControllerBase().':'.$this->getPostActionControllerAction('index'),
921
                        'passthroughVars' => [
922
                            'mauticContent' => $this->getJsLoadMethodPrefix(),
923
                        ],
924
                    ],
925
                    'index'
926
                )
927
            );
928
        }
929
930
        //set what page currently on so that we can return here after form submission/cancellation
931
        $session->set('mautic.'.$this->getSessionBase().'.page', $page);
932
933
        $viewParameters = [
934
            'permissionBase'  => $this->getPermissionBase(),
935
            'mauticContent'   => $this->getJsLoadMethodPrefix(),
936
            'sessionVar'      => $this->getSessionBase(),
937
            'actionRoute'     => $this->getActionRoute(),
938
            'indexRoute'      => $this->getIndexRoute(),
939
            'tablePrefix'     => $model->getRepository()->getTableAlias(),
940
            'modelName'       => $this->getModelName(),
941
            'translationBase' => $this->getTranslationBase(),
942
            'searchValue'     => $search,
943
            'items'           => $items,
944
            'totalItems'      => $count,
945
            'page'            => $page,
946
            'limit'           => $limit,
947
            'permissions'     => $permissions,
948
            'tmpl'            => $this->request->get('tmpl', 'index'),
949
        ];
950
951
        return $this->delegateView(
952
            $this->getViewArguments(
953
                [
954
                    'viewParameters'  => $viewParameters,
955
                    'contentTemplate' => $this->getTemplateName('list.html.php'),
956
                    'passthroughVars' => [
957
                        'mauticContent' => $this->getJsLoadMethodPrefix(),
958
                        'route'         => $this->generateUrl($this->getIndexRoute(), ['page' => $page]),
959
                    ],
960
                ],
961
                'index'
962
            )
963
        );
964
    }
965
966
    /**
967
     * @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
968
     *
969
     * @throws \Exception
970
     */
971
    protected function newStandard()
972
    {
973
        $entity = $this->getFormEntity('new');
974
975
        if (!$this->checkActionPermission('new')) {
976
            return $this->accessDenied();
977
        }
978
979
        $model = $this->getModel($this->getModelName());
980
        if (!$model instanceof FormModel) {
981
            throw new \Exception(get_class($model).' must extend '.FormModel::class);
982
        }
983
984
        //set the page we came from
985
        $page = $this->get('session')->get('mautic.'.$this->getSessionBase().'.page', 1);
986
987
        $options = $this->getEntityFormOptions();
988
        $action  = $this->generateUrl($this->getActionRoute(), ['objectAction' => 'new']);
989
        $form    = $model->createForm($entity, $this->get('form.factory'), $action, $options);
990
991
        ///Check for a submitted form and process it
992
        $isPost = 'POST' === $this->request->getMethod();
993
        $this->beforeFormProcessed($entity, $form, 'new', $isPost);
994
995
        if ($isPost) {
996
            $valid = false;
997
            if (!$cancelled = $this->isFormCancelled($form)) {
998
                if ($valid = $this->isFormValid($form)) {
999
                    if ($valid = $this->beforeEntitySave($entity, $form, 'new')) {
1000
                        $model->saveEntity($entity);
1001
                        $this->afterEntitySave($entity, $form, 'new', $valid);
1002
1003
                        if (method_exists($this, 'viewAction')) {
1004
                            $viewParameters = ['objectId' => $entity->getId(), 'objectAction' => 'view'];
1005
                            $returnUrl      = $this->generateUrl($this->getActionRoute(), $viewParameters);
1006
                            $template       = $this->getControllerBase().':view';
1007
                        } else {
1008
                            $viewParameters = ['page' => $page];
1009
                            $returnUrl      = $this->generateUrl($this->getIndexRoute(), $viewParameters);
1010
                            $template       = $this->getControllerBase().':'.$this->getPostActionControllerAction('new');
1011
                        }
1012
                    }
1013
                }
1014
1015
                $this->afterFormProcessed($valid, $entity, $form, 'new');
1016
            } else {
1017
                $viewParameters = ['page' => $page];
1018
                $returnUrl      = $this->generateUrl($this->getIndexRoute(), $viewParameters);
1019
                $template       = $this->getControllerBase().':'.$this->getPostActionControllerAction('new');
1020
            }
1021
1022
            $passthrough = [
1023
                'mauticContent' => $this->getJsLoadMethodPrefix(),
1024
            ];
1025
1026
            if ($isInPopup = isset($form['updateSelect'])) {
1027
                $template    = false;
1028
                $passthrough = array_merge(
1029
                    $passthrough,
1030
                    $this->getUpdateSelectParams($form['updateSelect']->getData(), $entity)
1031
                );
1032
            }
1033
1034
            if ($cancelled || ($valid && !$this->isFormApplied($form))) {
1035
                if ($isInPopup) {
1036
                    $passthrough['closeModal'] = true;
1037
                }
1038
1039
                return $this->postActionRedirect(
1040
                    $this->getPostActionRedirectArguments(
1041
                        [
1042
                            'returnUrl'       => $returnUrl,
1043
                            'viewParameters'  => $viewParameters,
1044
                            'contentTemplate' => $template,
1045
                            'passthroughVars' => $passthrough,
1046
                            'entity'          => $entity,
1047
                        ],
1048
                        'new'
1049
                    )
1050
                );
1051
            } elseif ($valid && $this->isFormApplied($form)) {
1052
                return $this->editAction($entity->getId(), true);
1053
            }
1054
        }
1055
1056
        $delegateArgs = [
1057
            'viewParameters' => [
1058
                'permissionBase'  => $this->getPermissionBase(),
1059
                'mauticContent'   => $this->getJsLoadMethodPrefix(),
1060
                'actionRoute'     => $this->getActionRoute(),
1061
                'indexRoute'      => $this->getIndexRoute(),
1062
                'tablePrefix'     => $model->getRepository()->getTableAlias(),
1063
                'modelName'       => $this->getModelName(),
1064
                'translationBase' => $this->getTranslationBase(),
1065
                'tmpl'            => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
1066
                'entity'          => $entity,
1067
                'form'            => $this->getFormView($form, 'new'),
1068
            ],
1069
            'contentTemplate' => $this->getTemplateName('form.html.php'),
1070
            'passthroughVars' => [
1071
                'mauticContent' => $this->getJsLoadMethodPrefix(),
1072
                'route'         => $this->generateUrl(
1073
                    $this->getActionRoute(),
1074
                    [
1075
                        'objectAction' => (!empty($valid) ? 'edit' : 'new'), //valid means a new form was applied
1076
                        'objectId'     => ($entity) ? $entity->getId() : 0,
1077
                    ]
1078
                ),
1079
                'validationError' => $this->getFormErrorForBuilder($form),
1080
            ],
1081
            'entity' => $entity,
1082
            'form'   => $form,
1083
        ];
1084
1085
        return $this->delegateView(
1086
            $this->getViewArguments($delegateArgs, 'new')
1087
        );
1088
    }
1089
1090
    /**
1091
     * @param null $name
1092
     */
1093
    protected function setListFilters($name = null)
1094
    {
1095
        return parent::setListFilters(($name) ? $name : $this->getSessionBase());
1096
    }
1097
1098
    /**
1099
     * @param        $objectId
1100
     * @param null   $logObject
1101
     * @param null   $logBundle
1102
     * @param null   $listPage
1103
     * @param string $itemName
1104
     *
1105
     * @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
1106
     */
1107
    protected function viewStandard($objectId, $logObject = null, $logBundle = null, $listPage = null, $itemName = 'item')
1108
    {
1109
        $model    = $this->getModel($this->getModelName());
1110
        $entity   = $model->getEntity($objectId);
1111
        $security = $this->get('mautic.security');
1112
1113
        if (null === $entity) {
1114
            $page = $this->get('session')->get('mautic.'.$this->getSessionBase().'.page', 1);
1115
1116
            return $this->postActionRedirect(
1117
                $this->getPostActionRedirectArguments(
1118
                    [
1119
                        'returnUrl'       => $this->generateUrl($this->getIndexRoute(), ['page' => $page]),
1120
                        'viewParameters'  => ['page' => $page],
1121
                        'contentTemplate' => $this->getControllerBase().':'.$this->getPostActionControllerAction('view'),
1122
                        'passthroughVars' => [
1123
                            'mauticContent' => $this->getJsLoadMethodPrefix(),
1124
                        ],
1125
                        'flashes' => [
1126
                            [
1127
                                'type'    => 'error',
1128
                                'msg'     => $this->getTranslatedString('error.notfound'),
1129
                                'msgVars' => ['%id%' => $objectId],
1130
                            ],
1131
                        ],
1132
                    ],
1133
                    'view'
1134
                )
1135
            );
1136
        } elseif (!$this->checkActionPermission('view', $entity)) {
1137
            return $this->accessDenied();
1138
        }
1139
1140
        $this->setListFilters();
1141
1142
        // Audit log entries
1143
        $logs = ($logObject) ? $this->getModel('core.auditlog')->getLogForObject($logObject, $objectId, $entity->getDateAdded(), 10, $logBundle) : [];
1144
1145
        // Generate route
1146
        $routeVars = [
1147
            'objectAction' => 'view',
1148
            'objectId'     => $entity->getId(),
1149
        ];
1150
        if (null !== $listPage) {
0 ignored issues
show
The condition null !== $listPage is always false.
Loading history...
1151
            $routeVars['listPage'] = $listPage;
1152
        }
1153
        $route = $this->generateUrl($this->getActionRoute(), $routeVars);
1154
1155
        $delegateArgs = [
1156
            'viewParameters' => [
1157
                $itemName     => $entity,
1158
                'logs'        => $logs,
1159
                'tmpl'        => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
1160
                'permissions' => $security->isGranted(
1161
                    [
1162
                        $this->getPermissionBase().':view',
1163
                        $this->getPermissionBase().':viewown',
1164
                        $this->getPermissionBase().':viewother',
1165
                        $this->getPermissionBase().':create',
1166
                        $this->getPermissionBase().':edit',
1167
                        $this->getPermissionBase().':editown',
1168
                        $this->getPermissionBase().':editother',
1169
                        $this->getPermissionBase().':delete',
1170
                        $this->getPermissionBase().':deleteown',
1171
                        $this->getPermissionBase().':deleteother',
1172
                        $this->getPermissionBase().':publish',
1173
                        $this->getPermissionBase().':publishown',
1174
                        $this->getPermissionBase().':publishother',
1175
                    ],
1176
                    'RETURN_ARRAY',
1177
                    null,
1178
                    true
1179
                ),
1180
            ],
1181
            'contentTemplate' => $this->getTemplateName('details.html.php'),
1182
            'passthroughVars' => [
1183
                'mauticContent' => $this->getJsLoadMethodPrefix(),
1184
                'route'         => $route,
1185
            ],
1186
            'objectId' => $objectId,
1187
            'entity'   => $entity,
1188
        ];
1189
1190
        return $this->delegateView(
1191
            $this->getViewArguments($delegateArgs, 'view')
1192
        );
1193
    }
1194
1195
    protected function getDataForExport(AbstractCommonModel $model, array $args, callable $resultsCallback = null, $start = 0)
1196
    {
1197
        return parent::getDataForExport($model, $args, $resultsCallback, $start); // TODO: Change the autogenerated stub
1198
    }
1199
}
1200