Issues (3627)

bundles/LeadBundle/Controller/FieldController.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2014 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\LeadBundle\Controller;
13
14
use Doctrine\DBAL\DBALException;
15
use Mautic\CoreBundle\Controller\FormController;
16
use Mautic\LeadBundle\Entity\LeadField;
17
use Mautic\LeadBundle\Model\FieldModel;
18
use Symfony\Component\Form\FormError;
19
20
class FieldController extends FormController
21
{
22
    /**
23
     * Generate's default list view.
24
     *
25
     * @param int $page
26
     *
27
     * @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
28
     */
29
    public function indexAction($page = 1)
30
    {
31
        //set some permissions
32
        $permissions = $this->get('mautic.security')->isGranted(['lead:fields:view', 'lead:fields:full'], 'RETURN_ARRAY');
33
34
        $session = $this->get('session');
35
36
        if (!$permissions['lead:fields:view'] && !$permissions['lead:fields:full']) {
37
            return $this->accessDenied();
38
        }
39
40
        $this->setListFilters();
41
42
        $limit  = $session->get('mautic.leadfield.limit', $this->coreParametersHelper->get('default_pagelimit'));
43
        $search = $this->request->get('search', $session->get('mautic.leadfield.filter', ''));
44
        $session->set('mautic.leadfilter.filter', $search);
45
46
        //do some default filtering
47
        $orderBy    = $this->get('session')->get('mautic.leadfilter.orderby', 'f.order');
48
        $orderByDir = $this->get('session')->get('mautic.leadfilter.orderbydir', 'ASC');
49
50
        $start = (1 === $page) ? 0 : (($page - 1) * $limit);
51
        if ($start < 0) {
52
            $start = 0;
53
        }
54
55
        $request = $this->factory->getRequest();
56
        $search  = $request->get('search', $session->get('mautic.lead.emailtoken.filter', ''));
57
58
        $session->set('mautic.lead.emailtoken.filter', $search);
59
60
        $fields = $this->getModel('lead.field')->getEntities([
61
            'start'      => $start,
62
            'limit'      => $limit,
63
            'filter'     => ['string' => $search],
64
            'orderBy'    => $orderBy,
65
            'orderByDir' => $orderByDir,
66
        ]);
67
        $count = count($fields);
68
69
        if ($count && $count < ($start + 1)) {
70
            //the number of entities are now less then the current page so redirect to the last page
71
            if (1 === $count) {
72
                $lastPage = 1;
73
            } else {
74
                $lastPage = (ceil($count / $limit)) ?: 1;
75
            }
76
            $session->set('mautic.leadfield.page', $lastPage);
77
            $returnUrl = $this->generateUrl('mautic_contactfield_index', ['page' => $lastPage]);
78
79
            return $this->postActionRedirect([
80
                'returnUrl'       => $returnUrl,
81
                'viewParameters'  => ['page' => $lastPage],
82
                'contentTemplate' => 'MauticLeadBundle:Field:index',
83
                'passthroughVars' => [
84
                    'activeLink'    => '#mautic_contactfield_index',
85
                    'mauticContent' => 'leadfield',
86
                ],
87
            ]);
88
        }
89
90
        //set what page currently on so that we can return here after form submission/cancellation
91
        $session->set('mautic.leadfield.page', $page);
92
93
        $tmpl = $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index';
94
95
        return $this->delegateView([
96
            'viewParameters' => [
97
                'items'       => $fields,
98
                'searchValue' => $search,
99
                'permissions' => $permissions,
100
                'tmpl'        => $tmpl,
101
                'totalItems'  => $count,
102
                'limit'       => $limit,
103
                'page'        => $page,
104
            ],
105
            'contentTemplate' => 'MauticLeadBundle:Field:list.html.php',
106
            'passthroughVars' => [
107
                'activeLink'    => '#mautic_contactfield_index',
108
                'route'         => $this->generateUrl('mautic_contactfield_index', ['page' => $page]),
109
                'mauticContent' => 'leadfield',
110
            ],
111
        ]);
112
    }
113
114
    /**
115
     * Generate's new form and processes post data.
116
     *
117
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
118
     */
119
    public function newAction()
120
    {
121
        if (!$this->get('mautic.security')->isGranted('lead:fields:full')) {
122
            return $this->accessDenied();
123
        }
124
125
        //retrieve the entity
126
        $field = new LeadField();
127
        /** @var FieldModel $model */
128
        $model = $this->getModel('lead.field');
129
        //set the return URL for post actions
130
        $returnUrl = $this->generateUrl('mautic_contactfield_index');
131
        $action    = $this->generateUrl('mautic_contactfield_action', ['objectAction' => 'new']);
132
        //get the user form factory
133
        $form = $model->createForm($field, $this->get('form.factory'), $action);
134
135
        ///Check for a submitted form and process it
136
        if ('POST' == $this->request->getMethod()) {
137
            $valid = false;
138
            if (!$cancelled = $this->isFormCancelled($form)) {
139
                if ($valid = $this->isFormValid($form)) {
140
                    $request = $this->request->request->all();
141
                    if (isset($request['leadfield']['properties'])) {
142
                        $result = $model->setFieldProperties($field, $request['leadfield']['properties']);
143
                        if (true !== $result) {
144
                            //set the error
145
                            $form->get('properties')->addError(
146
                                new FormError(
147
                                    $this->get('translator')->trans($result, [], 'validators')
148
                                )
149
                            );
150
                            $valid = false;
151
                        }
152
                    }
153
154
                    if ($valid) {
155
                        $flashMessage = 'mautic.core.notice.created';
156
                        try {
157
                            //form is valid so process the data
158
                            $model->saveEntity($field);
159
                        } catch (DBALException $ee) {
160
                            $flashMessage = $ee->getMessage();
161
                        } catch (\Exception $e) {
162
                            $form['alias']->addError(
163
                                    new FormError(
164
                                        $this->get('translator')->trans('mautic.lead.field.failed', ['%error%' => $e->getMessage()], 'validators')
165
                                    )
166
                                );
167
                            $valid = false;
168
                        }
169
                        $this->addFlash(
170
                                $flashMessage,
171
                                [
172
                                    '%name%'      => $field->getLabel(),
173
                                    '%menu_link%' => 'mautic_contactfield_index',
174
                                    '%url%'       => $this->generateUrl(
175
                                        'mautic_contactfield_action',
176
                                        [
177
                                            'objectAction' => 'edit',
178
                                            'objectId'     => $field->getId(),
179
                                        ]
180
                                    ),
181
                                ]
182
                            );
183
                    }
184
                }
185
            }
186
187
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
188
                return $this->postActionRedirect(
189
                    [
190
                        'returnUrl'       => $returnUrl,
191
                        'contentTemplate' => 'MauticLeadBundle:Field:index',
192
                        'passthroughVars' => [
193
                            'activeLink'    => '#mautic_contactfield_index',
194
                            'mauticContent' => 'leadfield',
195
                        ],
196
                    ]
197
                );
198
            } elseif ($valid && !$cancelled) {
199
                return $this->editAction($field->getId(), true);
200
            } elseif (!$valid) {
201
                // some bug in Symfony prevents repopulating list options on errors
202
                $field   = $form->getData();
203
                $newForm = $model->createForm($field, $this->get('form.factory'), $action);
204
                $this->copyErrorsRecursively($form, $newForm);
205
                $form = $newForm;
206
            }
207
        }
208
209
        return $this->delegateView(
210
            [
211
                'viewParameters' => [
212
                    'form' => $form->createView(),
213
                ],
214
                'contentTemplate' => 'MauticLeadBundle:Field:form.html.php',
215
                'passthroughVars' => [
216
                    'activeLink'    => '#mautic_contactfield_index',
217
                    'route'         => $this->generateUrl('mautic_contactfield_action', ['objectAction' => 'new']),
218
                    'mauticContent' => 'leadfield',
219
                ],
220
            ]
221
        );
222
    }
223
224
    /**
225
     * Generate's edit form and processes post data.
226
     *
227
     * @param            $objectId
228
     * @param bool|false $ignorePost
229
     *
230
     * @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
231
     */
232
    public function editAction($objectId, $ignorePost = false)
233
    {
234
        if (!$this->get('mautic.security')->isGranted('lead:fields:full')) {
235
            return $this->accessDenied();
236
        }
237
238
        /** @var FieldModel $model */
239
        $model = $this->getModel('lead.field');
240
        $field = $model->getEntity($objectId);
241
242
        //set the return URL
243
        $returnUrl = $this->generateUrl('mautic_contactfield_index');
244
245
        $postActionVars = [
246
            'returnUrl'       => $returnUrl,
247
            'contentTemplate' => 'MauticLeadBundle:Field:index',
248
            'passthroughVars' => [
249
                'activeLink'    => '#mautic_contactfield_index',
250
                'mauticContent' => 'leadfield',
251
            ],
252
        ];
253
        //list not found
254
        if (null === $field) {
255
            return $this->postActionRedirect(
256
                array_merge($postActionVars, [
257
                    'flashes' => [
258
                        [
259
                            'type'    => 'error',
260
                            'msg'     => 'mautic.lead.field.error.notfound',
261
                            'msgVars' => ['%id%' => $objectId],
262
                        ],
263
                    ],
264
                ])
265
            );
266
        } elseif ($model->isLocked($field)) {
267
            //deny access if the entity is locked
268
            return $this->isLocked($postActionVars, $field, 'lead.field');
269
        }
270
271
        $action = $this->generateUrl('mautic_contactfield_action', ['objectAction' => 'edit', 'objectId' => $objectId]);
272
        $form   = $model->createForm($field, $this->get('form.factory'), $action);
273
274
        ///Check for a submitted form and process it
275
        if (!$ignorePost && 'POST' == $this->request->getMethod()) {
276
            $valid = false;
277
            if (!$cancelled = $this->isFormCancelled($form)) {
278
                if ($valid = $this->isFormValid($form)) {
279
                    $request = $this->request->request->all();
280
                    if (isset($request['leadfield']['properties'])) {
281
                        $result = $model->setFieldProperties($field, $request['leadfield']['properties']);
282
                        if (true !== $result) {
283
                            //set the error
284
                            $form->get('properties')->addError(new FormError(
285
                                $this->get('translator')->trans($result, [], 'validators')
286
                            ));
287
                            $valid = false;
288
                        }
289
                    }
290
291
                    if ($valid) {
292
                        //form is valid so process the data
293
                        $model->saveEntity($field, $form->get('buttons')->get('save')->isClicked());
294
295
                        $this->addFlash('mautic.core.notice.updated', [
0 ignored issues
show
Deprecated Code introduced by
The function Mautic\CoreBundle\Contro...nController::addFlash() has been deprecated: Will be removed in Mautic 3.0. Use CommonController::flashBag->addFlash() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

295
                        /** @scrutinizer ignore-deprecated */ $this->addFlash('mautic.core.notice.updated', [

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
296
                            '%name%'      => $field->getLabel(),
297
                            '%menu_link%' => 'mautic_contactfield_index',
298
                            '%url%'       => $this->generateUrl('mautic_contactfield_action', [
299
                                'objectAction' => 'edit',
300
                                'objectId'     => $field->getId(),
301
                            ]),
302
                        ]);
303
                    }
304
                }
305
            } else {
306
                //unlock the entity
307
                $model->unlockEntity($field);
308
            }
309
310
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
311
                return $this->postActionRedirect(
312
                    array_merge($postActionVars, [
313
                            'viewParameters'  => ['objectId' => $field->getId()],
314
                            'contentTemplate' => 'MauticLeadBundle:Field:index',
315
                        ]
316
                    )
317
                );
318
            } elseif ($valid) {
319
                // Rebuild the form with new action so that apply doesn't keep creating a clone
320
                $action = $this->generateUrl('mautic_contactfield_action', ['objectAction' => 'edit', 'objectId' => $field->getId()]);
321
                $form   = $model->createForm($field, $this->get('form.factory'), $action);
322
            } else {
323
                // some bug in Symfony prevents repopulating list options on errors
324
                $field   = $form->getData();
325
                $newForm = $model->createForm($field, $this->get('form.factory'), $action);
326
                $this->copyErrorsRecursively($form, $newForm);
327
                $form = $newForm;
328
            }
329
        } else {
330
            //lock the entity
331
            $model->lockEntity($field);
332
        }
333
334
        return $this->delegateView([
335
            'viewParameters' => [
336
                'form' => $form->createView(),
337
            ],
338
            'contentTemplate' => 'MauticLeadBundle:Field:form.html.php',
339
            'passthroughVars' => [
340
                'activeLink'    => '#mautic_contactfield_index',
341
                'route'         => $action,
342
                'mauticContent' => 'leadfield',
343
            ],
344
        ]);
345
    }
346
347
    /**
348
     * Clone an entity.
349
     *
350
     * @param $objectId
351
     *
352
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
353
     */
354
    public function cloneAction($objectId)
355
    {
356
        $model  = $this->getModel('lead.field');
357
        $entity = $model->getEntity($objectId);
358
359
        if (null != $entity) {
360
            if (!$this->get('mautic.security')->isGranted('lead:fields:full')) {
361
                return $this->accessDenied();
362
            }
363
364
            $clone = clone $entity;
365
            $clone->setIsPublished(false);
366
            $clone->setIsFixed(false);
367
            $this->get('mautic.helper.field.alias')->makeAliasUnique($clone);
368
            $model->saveEntity($clone);
369
            $objectId = $clone->getId();
370
        }
371
372
        return $this->editAction($objectId);
373
    }
374
375
    /**
376
     * Delete a field.
377
     *
378
     * @param $objectId
379
     *
380
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
381
     */
382
    public function deleteAction($objectId)
383
    {
384
        if (!$this->get('mautic.security')->isGranted('lead:fields:full')) {
385
            return $this->accessDenied();
386
        }
387
388
        $returnUrl = $this->generateUrl('mautic_contactfield_index');
389
        $flashes   = [];
390
391
        $postActionVars = [
392
            'returnUrl'       => $returnUrl,
393
            'contentTemplate' => 'MauticLeadBundle:Field:index',
394
            'passthroughVars' => [
395
                'activeLink'    => '#mautic_contactfield_index',
396
                'mauticContent' => 'lead',
397
            ],
398
        ];
399
400
        if ('POST' == $this->request->getMethod()) {
401
            /** @var FieldModel $model */
402
            $model = $this->getModel('lead.field');
403
            $field = $model->getEntity($objectId);
404
405
            if (null === $field) {
406
                $flashes[] = [
407
                    'type'    => 'error',
408
                    'msg'     => 'mautic.lead.field.error.notfound',
409
                    'msgVars' => ['%id%' => $objectId],
410
                ];
411
            } elseif ($model->isLocked($field)) {
412
                return $this->isLocked($postActionVars, $field, 'lead.field');
413
            } elseif ($field->isFixed()) {
414
                //cannot delete fixed fields
415
                return $this->accessDenied();
416
            }
417
418
            $segments = [];
419
            foreach ($model->getFieldSegments($field) as $segment) {
420
                $segments[] = sprintf('"%s" (%d)', $segment->getName(), $segment->getId());
421
            }
422
423
            if (count($segments)) {
424
                $flashMessage = [
425
                    'type'    => 'error',
426
                    'msg'     => 'mautic.core.notice.used.field',
427
                    'msgVars' => [
428
                        '%name%'     => $field->getLabel(),
429
                        '%id%'       => $objectId,
430
                        '%segments%' => implode(', ', $segments),
431
                    ],
432
                ];
433
            } else {
434
                $model->deleteEntity($field);
435
                $flashMessage = [
436
                    'type'    => 'notice',
437
                    'msg'     => 'mautic.core.notice.deleted',
438
                    'msgVars' => [
439
                        '%name%' => $field->getLabel(),
440
                        '%id%'   => $objectId,
441
                    ],
442
                ];
443
            }
444
445
            $flashes[] = $flashMessage;
446
        } //else don't do anything
447
448
        return $this->postActionRedirect(
449
            array_merge($postActionVars, [
450
                'flashes' => $flashes,
451
            ])
452
        );
453
    }
454
455
    /**
456
     * Deletes a group of entities.
457
     *
458
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
459
     */
460
    public function batchDeleteAction()
461
    {
462
        if (!$this->get('mautic.security')->isGranted('lead:fields:full')) {
463
            return $this->accessDenied();
464
        }
465
466
        $returnUrl = $this->generateUrl('mautic_contactfield_index');
467
        $flashes   = [];
468
469
        $postActionVars = [
470
            'returnUrl'       => $returnUrl,
471
            'contentTemplate' => 'MauticLeadBundle:Field:index',
472
            'passthroughVars' => [
473
                'activeLink'    => '#mautic_contactfield_index',
474
                'mauticContent' => 'lead',
475
            ],
476
        ];
477
478
        if ('POST' == $this->request->getMethod()) {
479
            /** @var FieldModel $model */
480
            $model     = $this->getModel('lead.field');
481
            $ids       = json_decode($this->request->query->get('ids', '{}'));
482
            $deleteIds = [];
483
484
            // Loop over the IDs to perform access checks pre-delete
485
            foreach ($ids as $objectId) {
486
                $entity = $model->getEntity($objectId);
487
488
                if (null === $entity) {
489
                    $flashes[] = [
490
                        'type'    => 'error',
491
                        'msg'     => 'mautic.lead.field.error.notfound',
492
                        'msgVars' => ['%id%' => $objectId],
493
                    ];
494
                } elseif ($entity->isFixed()) {
495
                    $flashes[] = $this->accessDenied(true);
496
                } elseif ($model->isLocked($entity)) {
497
                    $flashes[] = $this->isLocked($postActionVars, $entity, 'lead.field', true);
498
                } else {
499
                    $deleteIds[] = $objectId;
500
                }
501
            }
502
503
            // Delete everything we are able to
504
            if (!empty($deleteIds)) {
505
                $filteredDeleteIds = $model->filterUsedFieldIds($deleteIds);
506
                $usedFieldIds      = array_diff($deleteIds, $filteredDeleteIds);
507
                $segments          = [];
508
                $usedFieldsNames   = [];
509
510
                if ($usedFieldIds) {
511
                    // Iterating through all used fileds to get segments they are used in
512
                    foreach ($usedFieldIds as $usedFieldId) {
513
                        $fieldEntity = $model->getEntity($usedFieldId);
514
                        foreach ($model->getFieldSegments($fieldEntity) as $segment) {
515
                            $segments[$segment->getId()] = sprintf('"%s" (%d)', $segment->getName(), $segment->getId());
516
                            $usedFieldsNames[]           = sprintf('"%s"', $fieldEntity->getName());
517
                        }
518
                    }
519
                }
520
521
                if ($filteredDeleteIds !== $deleteIds) {
522
                    $flashes[] = [
523
                        'type'    => 'error',
524
                        'msg'     => 'mautic.core.notice.used.fields',
525
                        'msgVars' => [
526
                            '%segments%' => implode(', ', $segments),
527
                            '%fields%'   => implode(', ', array_unique($usedFieldsNames)),
528
                        ],
529
                    ];
530
                }
531
532
                if (count($filteredDeleteIds)) {
533
                    $entities = $model->deleteEntities($filteredDeleteIds);
534
535
                    $flashes[] = [
536
                        'type'    => 'notice',
537
                        'msg'     => 'mautic.lead.field.notice.batch_deleted',
538
                        'msgVars' => [
539
                            '%count%' => count($entities),
540
                        ],
541
                    ];
542
                }
543
            }
544
        } //else don't do anything
545
546
        return $this->postActionRedirect(
547
            array_merge($postActionVars, [
548
                'flashes' => $flashes,
549
            ])
550
        );
551
    }
552
}
553