Issues (3627)

bundles/PageBundle/Controller/PageController.php (2 issues)

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\PageBundle\Controller;
13
14
use Mautic\CoreBundle\Controller\BuilderControllerTrait;
15
use Mautic\CoreBundle\Controller\FormController;
16
use Mautic\CoreBundle\Controller\FormErrorMessagesTrait;
17
use Mautic\CoreBundle\Event\DetermineWinnerEvent;
18
use Mautic\CoreBundle\Factory\PageHelperFactoryInterface;
19
use Mautic\CoreBundle\Form\Type\BuilderSectionType;
20
use Mautic\CoreBundle\Form\Type\DateRangeType;
21
use Mautic\CoreBundle\Helper\InputHelper;
22
use Mautic\PageBundle\Entity\Page;
23
use Symfony\Component\HttpFoundation\JsonResponse;
24
25
class PageController extends FormController
26
{
27
    use BuilderControllerTrait;
28
    use FormErrorMessagesTrait;
29
30
    /**
31
     * @param int $page
32
     *
33
     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
34
     */
35
    public function indexAction($page = 1)
36
    {
37
        $model = $this->getModel('page.page');
38
39
        //set some permissions
40
        $permissions = $this->get('mautic.security')->isGranted([
41
            'page:pages:viewown',
42
            'page:pages:viewother',
43
            'page:pages:create',
44
            'page:pages:editown',
45
            'page:pages:editother',
46
            'page:pages:deleteown',
47
            'page:pages:deleteother',
48
            'page:pages:publishown',
49
            'page:pages:publishother',
50
            'page:preference_center:viewown',
51
            'page:preference_center:viewother',
52
        ], 'RETURN_ARRAY');
53
54
        if (!$permissions['page:pages:viewown'] && !$permissions['page:pages:viewother']) {
55
            return $this->accessDenied();
56
        }
57
58
        $this->setListFilters();
59
60
        /** @var PageHelperFactoryInterface $pageHelperFacotry */
61
        $pageHelperFacotry = $this->get('mautic.page.helper.factory');
62
        $pageHelper        = $pageHelperFacotry->make('mautic.page', $page);
63
64
        $limit  = $pageHelper->getLimit();
65
        $start  = $pageHelper->getStart();
66
        $search = $this->request->get('search', $this->get('session')->get('mautic.page.filter', ''));
67
        $filter = ['string' => $search, 'force' => []];
68
69
        $this->get('session')->set('mautic.page.filter', $search);
70
71
        if (!$permissions['page:pages:viewother']) {
72
            $filter['force'][] = ['column' => 'p.createdBy', 'expr' => 'eq', 'value' => $this->user->getId()];
73
        }
74
75
        if (!$permissions['page:preference_center:viewown'] && !$permissions['page:preference_center:viewother']) {
76
            $filter['where'][] = [
77
                'expr' => 'orX',
78
                'val'  => [
79
                    ['column' => 'p.isPreferenceCenter', 'expr' => 'isNull'],
80
                    ['column' => 'p.isPreferenceCenter', 'expr' => 'eq', 'value' => 0],
81
                ],
82
            ];
83
        } elseif (!$permissions['page:preference_center:viewother']) {
84
            $filter['where'][] = [
85
                'expr' => 'orX',
86
                'val'  => [
87
                        [
88
                            'expr' => 'orX',
89
                            'val'  => [
90
                                ['column' => 'p.isPreferenceCenter', 'expr' => 'isNull'],
91
                                ['column' => 'p.isPreferenceCenter', 'expr' => 'eq', 'value' => 0],
92
                            ],
93
                        ],
94
                        [
95
                            'expr' => 'andX',
96
                            'val'  => [
97
                                ['column' => 'p.isPreferenceCenter', 'expr' => 'eq', 'value' => 1],
98
                                ['column' => 'p.createdBy', 'expr' => 'eq', 'value' => $this->user->getId()],
99
                            ],
100
                        ],
101
                    ],
102
                ];
103
        }
104
105
        $translator = $this->get('translator');
106
107
        //do not list variants in the main list
108
        $filter['force'][] = ['column' => 'p.variantParent', 'expr' => 'isNull'];
109
110
        $langSearchCommand = $translator->trans('mautic.core.searchcommand.lang');
111
        if (false === strpos($search, "{$langSearchCommand}:")) {
112
            $filter['force'][] = ['column' => 'p.translationParent', 'expr' => 'isNull'];
113
        }
114
115
        $orderBy    = $this->get('session')->get('mautic.page.orderby', 'p.title');
116
        $orderByDir = $this->get('session')->get('mautic.page.orderbydir', 'DESC');
117
        $pages      = $model->getEntities(
118
            [
119
                'start'      => $start,
120
                'limit'      => $limit,
121
                'filter'     => $filter,
122
                'orderBy'    => $orderBy,
123
                'orderByDir' => $orderByDir,
124
            ]);
125
126
        $count = count($pages);
127
        if ($count && $count < ($start + 1)) {
128
            $lastPage  = $pageHelper->countPage($count);
129
            $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $lastPage]);
130
            $pageHelper->rememberPage($lastPage);
131
132
            return $this->postActionRedirect([
133
                'returnUrl'       => $returnUrl,
134
                'viewParameters'  => ['page' => $lastPage],
135
                'contentTemplate' => 'MauticPageBundle:Page:index',
136
                'passthroughVars' => [
137
                    'activeLink'    => '#mautic_page_index',
138
                    'mauticContent' => 'page',
139
                ],
140
            ]);
141
        }
142
143
        $pageHelper->rememberPage($page);
144
145
        return $this->delegateView([
146
            'viewParameters' => [
147
                'searchValue' => $search,
148
                'items'       => $pages,
149
                'categories'  => $this->getModel('page.page')->getLookupResults('category', '', 0),
150
                'page'        => $page,
151
                'limit'       => $limit,
152
                'permissions' => $permissions,
153
                'model'       => $model,
154
                'tmpl'        => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
155
                'security'    => $this->get('mautic.security'),
156
            ],
157
            'contentTemplate' => 'MauticPageBundle:Page:list.html.php',
158
            'passthroughVars' => [
159
                'activeLink'    => '#mautic_page_index',
160
                'mauticContent' => 'page',
161
                'route'         => $this->generateUrl('mautic_page_index', ['page' => $page]),
162
            ],
163
        ]);
164
    }
165
166
    /**
167
     * Loads a specific form into the detailed panel.
168
     *
169
     * @param int $objectId
170
     *
171
     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
172
     */
173
    public function viewAction($objectId)
174
    {
175
        /** @var \Mautic\PageBundle\Model\PageModel $model */
176
        $model = $this->getModel('page.page');
177
        //set some permissions
178
        $security   = $this->get('mautic.security');
179
        $activePage = $model->getEntity($objectId);
180
        //set the page we came from
181
        $page = $this->get('session')->get('mautic.page.page', 1);
182
183
        if (null === $activePage) {
184
            //set the return URL
185
            $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $page]);
186
187
            return $this->postActionRedirect([
188
                'returnUrl'       => $returnUrl,
189
                'viewParameters'  => ['page' => $page],
190
                'contentTemplate' => 'MauticPageBundle:Page:index',
191
                'passthroughVars' => [
192
                    'activeLink'    => '#mautic_page_index',
193
                    'mauticContent' => 'page',
194
                ],
195
                'flashes' => [
196
                    [
197
                        'type'    => 'error',
198
                        'msg'     => 'mautic.page.error.notfound',
199
                        'msgVars' => ['%id%' => $objectId],
200
                    ],
201
                ],
202
            ]);
203
        } elseif (!$security->hasEntityAccess(
204
                'page:pages:viewown', 'page:pages:viewother', $activePage->getCreatedBy()
205
            ) ||
206
            ($activePage->getIsPreferenceCenter() &&
207
                !$security->hasEntityAccess(
208
                    'page:preference_center:viewown', 'page:preference_center:viewother', $activePage->getCreatedBy()
209
                ))) {
210
            return $this->accessDenied();
211
        }
212
213
        //get A/B test information
214
        list($parent, $children) = $activePage->getVariants();
215
        $properties              = [];
216
        $variantError            = false;
217
        $weight                  = 0;
218
        if (count($children)) {
219
            foreach ($children as $c) {
220
                $variantSettings = $c->getVariantSettings();
221
222
                if (is_array($variantSettings) && isset($variantSettings['winnerCriteria'])) {
223
                    if ($c->isPublished()) {
224
                        if (!isset($lastCriteria)) {
225
                            $lastCriteria = $variantSettings['winnerCriteria'];
226
                        }
227
228
                        //make sure all the variants are configured with the same criteria
229
                        if ($lastCriteria != $variantSettings['winnerCriteria']) {
230
                            $variantError = true;
231
                        }
232
233
                        $weight += $variantSettings['weight'];
234
                    }
235
                } else {
236
                    $variantSettings['winnerCriteria'] = '';
237
                    $variantSettings['weight']         = 0;
238
                }
239
240
                $properties[$c->getId()] = $variantSettings;
241
            }
242
243
            $properties[$parent->getId()]['weight']         = 100 - $weight;
244
            $properties[$parent->getId()]['winnerCriteria'] = '';
245
        }
246
247
        $abTestResults = [];
248
        $criteria      = $model->getBuilderComponents($activePage, 'abTestWinnerCriteria');
249
        if (!empty($lastCriteria) && empty($variantError)) {
250
            //there is a criteria to compare the pages against so let's shoot the page over to the criteria function to do its thing
251
            if (isset($criteria['criteria'][$lastCriteria])) {
252
                $testSettings = $criteria['criteria'][$lastCriteria];
253
254
                $args = [
255
                    'page'       => $activePage,
256
                    'parent'     => $parent,
257
                    'children'   => $children,
258
                    'properties' => $properties,
259
                ];
260
261
                $event = new DetermineWinnerEvent($args);
262
                $this->dispatcher->dispatch(
263
                    $testSettings['event'],
264
                    $event
265
                );
266
267
                $abTestResults = $event->getAbTestResults();
268
            }
269
        }
270
271
        // Init the date range filter form
272
        $dateRangeValues = $this->request->get('daterange', []);
273
        $action          = $this->generateUrl('mautic_page_action', ['objectAction' => 'view', 'objectId' => $objectId]);
274
        $dateRangeForm   = $this->get('form.factory')->create(DateRangeType::class, $dateRangeValues, ['action' => $action]);
275
276
        // Audit Log
277
        $logs = $this->getModel('core.auditlog')->getLogForObject('page', $activePage->getId(), $activePage->getDateAdded());
278
279
        $pageviews = $model->getHitsLineChartData(
280
            null,
281
            new \DateTime($dateRangeForm->get('date_from')->getData()),
282
            new \DateTime($dateRangeForm->get('date_to')->getData()),
283
            null,
284
            ['page_id' => $activePage->getId(), 'flag' => 'total_and_unique']
285
        );
286
287
        //get related translations
288
        list($translationParent, $translationChildren) = $activePage->getTranslations();
289
290
        return $this->delegateView([
291
            'returnUrl' => $this->generateUrl('mautic_page_action', [
292
                    'objectAction' => 'view',
293
                    'objectId'     => $activePage->getId(), ]
294
            ),
295
            'viewParameters' => [
296
                'activePage' => $activePage,
297
                'variants'   => [
298
                    'parent'     => $parent,
299
                    'children'   => $children,
300
                    'properties' => $properties,
301
                    'criteria'   => $criteria['criteria'],
302
                ],
303
                'translations' => [
304
                    'parent'   => $translationParent,
305
                    'children' => $translationChildren,
306
                ],
307
                'permissions' => $security->isGranted([
308
                    'page:pages:viewown',
309
                    'page:pages:viewother',
310
                    'page:pages:create',
311
                    'page:pages:editown',
312
                    'page:pages:editother',
313
                    'page:pages:deleteown',
314
                    'page:pages:deleteother',
315
                    'page:pages:publishown',
316
                    'page:pages:publishother',
317
                    'page:preference_center:viewown',
318
                    'page:preference_center:viewother',
319
                ], 'RETURN_ARRAY'),
320
                'stats' => [
321
                    'pageviews' => $pageviews,
322
                    'hits'      => [
323
                        'total'  => $activePage->getHits(),
324
                        'unique' => $activePage->getUniqueHits(),
325
                    ],
326
                ],
327
                'abTestResults' => $abTestResults,
328
                'security'      => $security,
329
                'pageUrl'       => $model->generateUrl($activePage, true),
330
                'previewUrl'    => $this->generateUrl('mautic_page_preview', ['id' => $objectId], true),
331
                'logs'          => $logs,
332
                'dateRangeForm' => $dateRangeForm->createView(),
333
            ],
334
            'contentTemplate' => 'MauticPageBundle:Page:details.html.php',
335
            'passthroughVars' => [
336
                'activeLink'    => '#mautic_page_index',
337
                'mauticContent' => 'page',
338
            ],
339
        ]);
340
    }
341
342
    /**
343
     * Generates new form and processes post data.
344
     *
345
     * @param \Mautic\PageBundle\Entity\Page|null $entity
346
     *
347
     * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
348
     */
349
    public function newAction($entity = null)
350
    {
351
        /** @var \Mautic\PageBundle\Model\PageModel $model */
352
        $model = $this->getModel('page.page');
353
354
        if (!($entity instanceof Page)) {
355
            /** @var \Mautic\PageBundle\Entity\Page $entity */
356
            $entity = $model->getEntity();
357
        }
358
359
        $method  = $this->request->getMethod();
360
        $session = $this->get('session');
361
        if (!$this->get('mautic.security')->isGranted('page:pages:create')) {
362
            return $this->accessDenied();
363
        }
364
365
        //set the page we came from
366
        $page   = $session->get('mautic.page.page', 1);
367
        $action = $this->generateUrl('mautic_page_action', ['objectAction' => 'new']);
368
369
        //create the form
370
        $form = $model->createForm($entity, $this->get('form.factory'), $action);
371
372
        ///Check for a submitted form and process it
373
        if ('POST' == $method) {
374
            $valid = false;
375
            if (!$cancelled = $this->isFormCancelled($form)) {
376
                if ($valid = $this->isFormValid($form)) {
377
                    $content = $entity->getCustomHtml();
378
                    $entity->setCustomHtml($content);
379
380
                    //form is valid so process the data
381
                    $model->saveEntity($entity);
382
383
                    $this->addFlash('mautic.core.notice.created', [
384
                        '%name%'      => $entity->getTitle(),
385
                        '%menu_link%' => 'mautic_page_index',
386
                        '%url%'       => $this->generateUrl('mautic_page_action', [
387
                            'objectAction' => 'edit',
388
                            'objectId'     => $entity->getId(),
389
                        ]),
390
                    ]);
391
392
                    if ($form->get('buttons')->get('save')->isClicked()) {
393
                        $viewParameters = [
394
                            'objectAction' => 'view',
395
                            'objectId'     => $entity->getId(),
396
                        ];
397
                        $returnUrl = $this->generateUrl('mautic_page_action', $viewParameters);
398
                        $template  = 'MauticPageBundle:Page:view';
399
                    } else {
400
                        //return edit view so that all the session stuff is loaded
401
                        return $this->editAction($entity->getId(), true);
402
                    }
403
                }
404
            } else {
405
                $viewParameters = ['page' => $page];
406
                $returnUrl      = $this->generateUrl('mautic_page_index', $viewParameters);
407
                $template       = 'MauticPageBundle:Page:index';
408
                //clear any modified content
409
                $session->remove('mautic.pagebuilder.'.$entity->getSessionId().'.content');
410
            }
411
412
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
413
                return $this->postActionRedirect([
414
                    'returnUrl'       => $returnUrl,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $returnUrl does not seem to be defined for all execution paths leading up to this point.
Loading history...
415
                    'viewParameters'  => $viewParameters,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $viewParameters does not seem to be defined for all execution paths leading up to this point.
Loading history...
416
                    'contentTemplate' => $template,
417
                    'passthroughVars' => [
418
                        'activeLink'    => 'mautic_page_index',
419
                        'mauticContent' => 'page',
420
                    ],
421
                ]);
422
            }
423
        }
424
425
        $slotTypes   = $model->getBuilderComponents($entity, 'slotTypes');
426
        $sections    = $model->getBuilderComponents($entity, 'sections');
427
        $sectionForm = $this->get('form.factory')->create(BuilderSectionType::class);
428
429
        //set some permissions
430
        $permissions = $this->get('mautic.security')->isGranted(
431
            [
432
                'page:preference_center:editown',
433
                'page:preference_center:editother',
434
            ],
435
            'RETURN_ARRAY'
436
        );
437
438
        return $this->delegateView([
439
            'viewParameters' => [
440
                'form'          => $this->setFormTheme($form, 'MauticPageBundle:Page:form.html.php', 'MauticPageBundle:FormTheme\Page'),
441
                'isVariant'     => $entity->isVariant(true),
442
                'tokens'        => $model->getBuilderComponents($entity, 'tokens'),
443
                'activePage'    => $entity,
444
                'themes'        => $this->factory->getInstalledThemes('page', true),
445
                'slots'         => $this->buildSlotForms($slotTypes),
446
                'sections'      => $this->buildSlotForms($sections),
447
                'builderAssets' => trim(preg_replace('/\s+/', ' ', $this->getAssetsForBuilder())), // strip new lines
448
                'sectionForm'   => $sectionForm->createView(),
449
                'permissions'   => $permissions,
450
            ],
451
            'contentTemplate' => 'MauticPageBundle:Page:form.html.php',
452
            'passthroughVars' => [
453
                'activeLink'    => '#mautic_page_index',
454
                'mauticContent' => 'page',
455
                'route'         => $this->generateUrl('mautic_page_action', [
456
                    'objectAction' => 'new',
457
                ]),
458
                'validationError' => $this->getFormErrorForBuilder($form),
459
            ],
460
        ]);
461
    }
462
463
    /**
464
     * Generates edit form and processes post data.
465
     *
466
     * @param int  $objectId
467
     * @param bool $ignorePost
468
     *
469
     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
470
     */
471
    public function editAction($objectId, $ignorePost = false)
472
    {
473
        /** @var \Mautic\PageBundle\Model\PageModel $model */
474
        $model    = $this->getModel('page.page');
475
        $security = $this->get('mautic.security');
476
        $entity   = $model->getEntity($objectId);
477
        $session  = $this->get('session');
478
        $page     = $this->get('session')->get('mautic.page.page', 1);
479
480
        //set the return URL
481
        $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $page]);
482
483
        $postActionVars = [
484
            'returnUrl'       => $returnUrl,
485
            'viewParameters'  => ['page' => $page],
486
            'contentTemplate' => 'MauticPageBundle:Page:index',
487
            'passthroughVars' => [
488
                'activeLink'    => 'mautic_page_index',
489
                'mauticContent' => 'page',
490
            ],
491
        ];
492
493
        //not found
494
        if (null === $entity) {
495
            return $this->postActionRedirect(
496
                array_merge($postActionVars, [
497
                    'flashes' => [
498
                        [
499
                            'type'    => 'error',
500
                            'msg'     => 'mautic.page.error.notfound',
501
                            'msgVars' => ['%id%' => $objectId],
502
                        ],
503
                    ],
504
                ])
505
            );
506
        } elseif (!$security->hasEntityAccess(
507
            'page:pages:viewown', 'page:pages:viewother', $entity->getCreatedBy()
508
        ) ||
509
            ($entity->getIsPreferenceCenter() && !$security->hasEntityAccess(
510
                    'page:preference_center:viewown', 'page:preference_center:viewother', $entity->getCreatedBy()
511
                ))) {
512
            return $this->accessDenied();
513
        } elseif ($model->isLocked($entity)) {
514
            //deny access if the entity is locked
515
            return $this->isLocked($postActionVars, $entity, 'page.page');
516
        }
517
518
        //Create the form
519
        $action = $this->generateUrl('mautic_page_action', ['objectAction' => 'edit', 'objectId' => $objectId]);
520
        $form   = $model->createForm($entity, $this->get('form.factory'), $action);
521
522
        ///Check for a submitted form and process it
523
        if (!$ignorePost && 'POST' == $this->request->getMethod()) {
524
            $valid = false;
525
            if (!$cancelled = $this->isFormCancelled($form)) {
526
                if ($valid = $this->isFormValid($form)) {
527
                    $content = $entity->getCustomHtml();
528
                    $entity->setCustomHtml($content);
529
530
                    //form is valid so process the data
531
                    $model->saveEntity($entity, $form->get('buttons')->get('save')->isClicked());
532
533
                    $this->addFlash('mautic.core.notice.updated', [
534
                        '%name%'      => $entity->getTitle(),
535
                        '%menu_link%' => 'mautic_page_index',
536
                        '%url%'       => $this->generateUrl('mautic_page_action', [
537
                            'objectAction' => 'edit',
538
                            'objectId'     => $entity->getId(),
539
                        ]),
540
                    ]);
541
                }
542
            } else {
543
                //clear any modified content
544
                $session->remove('mautic.pagebuilder.'.$objectId.'.content');
545
                //unlock the entity
546
                $model->unlockEntity($entity);
547
            }
548
549
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
550
                $viewParameters = [
551
                    'objectAction' => 'view',
552
                    'objectId'     => $entity->getId(),
553
                ];
554
555
                return $this->postActionRedirect(
556
                    array_merge($postActionVars, [
557
                        'returnUrl'       => $this->generateUrl('mautic_page_action', $viewParameters),
558
                        'viewParameters'  => $viewParameters,
559
                        'contentTemplate' => 'MauticPageBundle:Page:view',
560
                    ])
561
                );
562
            }
563
        } else {
564
            //lock the entity
565
            $model->lockEntity($entity);
566
567
            //clear any modified content
568
            $session->remove('mautic.pagebuilder.'.$objectId.'.content');
569
570
            //set the lookup values
571
            $parent = $entity->getTranslationParent();
572
            if ($parent && isset($form['translationParent_lookup'])) {
573
                $form->get('translationParent_lookup')->setData($parent->getTitle());
574
            }
575
576
            // Set to view content
577
            $template = $entity->getTemplate();
578
            if (empty($template)) {
579
                $content = $entity->getCustomHtml();
580
                $form['customHtml']->setData($content);
581
            }
582
        }
583
584
        $slotTypes   = $model->getBuilderComponents($entity, 'slotTypes');
585
        $sections    = $model->getBuilderComponents($entity, 'sections');
586
        $sectionForm = $this->get('form.factory')->create(BuilderSectionType::class);
587
588
        return $this->delegateView([
589
            'viewParameters' => [
590
                'form'          => $this->setFormTheme($form, 'MauticPageBundle:Page:form.html.php', 'MauticPageBundle:FormTheme\Page'),
591
                'isVariant'     => $entity->isVariant(true),
592
                'tokens'        => $model->getBuilderComponents($entity, 'tokens'),
593
                'activePage'    => $entity,
594
                'themes'        => $this->factory->getInstalledThemes('page', true),
595
                'slots'         => $this->buildSlotForms($slotTypes),
596
                'sections'      => $this->buildSlotForms($sections),
597
                'builderAssets' => trim(preg_replace('/\s+/', ' ', $this->getAssetsForBuilder())), // strip new lines
598
                'sectionForm'   => $sectionForm->createView(),
599
                'previewUrl'    => $this->generateUrl('mautic_page_preview', ['id' => $objectId], true),
600
                'permissions'   => $security->isGranted(
601
                    [
602
                        'page:preference_center:editown',
603
                        'page:preference_center:editother',
604
                    ],
605
                    'RETURN_ARRAY'
606
                ),
607
                'security'      => $security,
608
            ],
609
            'contentTemplate' => 'MauticPageBundle:Page:form.html.php',
610
            'passthroughVars' => [
611
                'activeLink'    => '#mautic_page_index',
612
                'mauticContent' => 'page',
613
                'route'         => $this->generateUrl('mautic_page_action', [
614
                    'objectAction' => 'edit',
615
                    'objectId'     => $entity->getId(),
616
                ]),
617
                'validationError' => $this->getFormErrorForBuilder($form),
618
            ],
619
        ]);
620
    }
621
622
    /**
623
     * Clone an entity.
624
     *
625
     * @param int $objectId
626
     *
627
     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
628
     */
629
    public function cloneAction($objectId)
630
    {
631
        /** @var \Mautic\PageBundle\Model\PageModel $model */
632
        $model  = $this->getModel('page.page');
633
        $entity = $model->getEntity($objectId);
634
635
        if (null != $entity) {
636
            if (!$this->get('mautic.security')->isGranted('page:pages:create') ||
637
                !$this->get('mautic.security')->hasEntityAccess(
638
                    'page:pages:viewown', 'page:pages:viewother', $entity->getCreatedBy()
639
                )
640
            ) {
641
                return $this->accessDenied();
642
            }
643
644
            $entity = clone $entity;
645
            $entity->setHits(0);
646
            $entity->setUniqueHits(0);
647
            $entity->setRevision(0);
648
            $entity->setVariantStartDate(null);
649
            $entity->setVariantHits(0);
650
            $entity->setIsPublished(false);
651
652
            $session     = $this->get('session');
653
            $contentName = 'mautic.pagebuilder.'.$entity->getSessionId().'.content';
654
655
            $session->set($contentName, $entity->getCustomHtml());
656
        }
657
658
        return $this->newAction($entity);
659
    }
660
661
    /**
662
     * Deletes the entity.
663
     *
664
     * @param $objectId
665
     *
666
     * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
667
     */
668
    public function deleteAction($objectId)
669
    {
670
        $page      = $this->get('session')->get('mautic.page.page', 1);
671
        $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $page]);
672
        $flashes   = [];
673
674
        $postActionVars = [
675
            'returnUrl'       => $returnUrl,
676
            'viewParameters'  => ['page' => $page],
677
            'contentTemplate' => 'MauticPageBundle:Page:index',
678
            'passthroughVars' => [
679
                'activeLink'    => 'mautic_page_index',
680
                'mauticContent' => 'page',
681
            ],
682
        ];
683
684
        if ('POST' == $this->request->getMethod()) {
685
            /** @var \Mautic\PageBundle\Model\PageModel $model */
686
            $model  = $this->getModel('page.page');
687
            $entity = $model->getEntity($objectId);
688
689
            if (null === $entity) {
690
                $flashes[] = [
691
                    'type'    => 'error',
692
                    'msg'     => 'mautic.page.error.notfound',
693
                    'msgVars' => ['%id%' => $objectId],
694
                ];
695
            } elseif (!$this->get('mautic.security')->hasEntityAccess(
696
                'page:pages:deleteown',
697
                'page:pages:deleteother',
698
                $entity->getCreatedBy()
699
            )) {
700
                return $this->accessDenied();
701
            } elseif ($model->isLocked($entity)) {
702
                return $this->isLocked($postActionVars, $entity, 'page.page');
703
            }
704
705
            $model->deleteEntity($entity);
706
707
            $flashes[] = [
708
                'type'    => 'notice',
709
                'msg'     => 'mautic.core.notice.deleted',
710
                'msgVars' => [
711
                    '%name%' => $entity->getTitle(),
712
                    '%id%'   => $objectId,
713
                ],
714
            ];
715
        } //else don't do anything
716
717
        return $this->postActionRedirect(
718
            array_merge($postActionVars, [
719
                'flashes' => $flashes,
720
            ])
721
        );
722
    }
723
724
    /**
725
     * Deletes a group of entities.
726
     *
727
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
728
     */
729
    public function batchDeleteAction()
730
    {
731
        $page      = $this->get('session')->get('mautic.page.page', 1);
732
        $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $page]);
733
        $flashes   = [];
734
735
        $postActionVars = [
736
            'returnUrl'       => $returnUrl,
737
            'viewParameters'  => ['page' => $page],
738
            'contentTemplate' => 'MauticPageBundle:Page:index',
739
            'passthroughVars' => [
740
                'activeLink'    => 'mautic_page_index',
741
                'mauticContent' => 'page',
742
            ],
743
        ];
744
745
        if ('POST' == $this->request->getMethod()) {
746
            /** @var \Mautic\PageBundle\Model\PageModel $model */
747
            $model     = $this->getModel('page');
748
            $ids       = json_decode($this->request->query->get('ids', '{}'));
749
            $deleteIds = [];
750
751
            // Loop over the IDs to perform access checks pre-delete
752
            foreach ($ids as $objectId) {
753
                $entity = $model->getEntity($objectId);
754
755
                if (null === $entity) {
756
                    $flashes[] = [
757
                        'type'    => 'error',
758
                        'msg'     => 'mautic.page.error.notfound',
759
                        'msgVars' => ['%id%' => $objectId],
760
                    ];
761
                } elseif (!$this->get('mautic.security')->hasEntityAccess(
762
                    'page:pages:deleteown', 'page:pages:deleteother', $entity->getCreatedBy()
763
                )) {
764
                    $flashes[] = $this->accessDenied(true);
765
                } elseif ($model->isLocked($entity)) {
766
                    $flashes[] = $this->isLocked($postActionVars, $entity, 'page', true);
767
                } else {
768
                    $deleteIds[] = $objectId;
769
                }
770
            }
771
772
            // Delete everything we are able to
773
            if (!empty($deleteIds)) {
774
                $entities = $model->deleteEntities($deleteIds);
775
776
                $flashes[] = [
777
                    'type'    => 'notice',
778
                    'msg'     => 'mautic.page.notice.batch_deleted',
779
                    'msgVars' => [
780
                        '%count%' => count($entities),
781
                    ],
782
                ];
783
            }
784
        } //else don't do anything
785
786
        return $this->postActionRedirect(
787
            array_merge($postActionVars, [
788
                'flashes' => $flashes,
789
            ])
790
        );
791
    }
792
793
    /**
794
     * Activate the builder.
795
     *
796
     * @param int $objectId
797
     *
798
     * @return \Symfony\Component\HttpFoundation\Response
799
     */
800
    public function builderAction($objectId)
801
    {
802
        /** @var \Mautic\PageBundle\Model\PageModel $model */
803
        $model = $this->getModel('page.page');
804
805
        //permission check
806
        if (false !== strpos($objectId, 'new')) {
807
            $isNew = true;
808
            if (!$this->get('mautic.security')->isGranted('page:pages:create')) {
809
                return $this->accessDenied();
810
            }
811
            $entity = $model->getEntity();
812
            $entity->setSessionId($objectId);
813
        } else {
814
            $isNew  = false;
815
            $entity = $model->getEntity($objectId);
816
            if (null == $entity || !$this->get('mautic.security')->hasEntityAccess(
817
                'page:pages:viewown', 'page:pages:viewother', $entity->getCreatedBy()
818
            )) {
819
                return $this->accessDenied();
820
            }
821
        }
822
823
        $template = InputHelper::clean($this->request->query->get('template'));
824
        $slots    = $this->factory->getTheme($template)->getSlots('page');
825
826
        //merge any existing changes
827
        $newContent = $this->get('session')->get('mautic.pagebuilder.'.$objectId.'.content', []);
828
        $content    = $entity->getContent();
829
830
        if (is_array($newContent)) {
831
            $content = array_merge($content, $newContent);
832
            // Update the content for processSlots
833
            $entity->setContent($content);
834
        }
835
836
        $this->processSlots($slots, $entity);
837
838
        $logicalName = $this->factory->getHelper('theme')->checkForTwigTemplate(':'.$template.':page.html.php');
839
840
        return $this->render($logicalName, [
841
            'isNew'       => $isNew,
842
            'slots'       => $slots,
843
            'formFactory' => $this->get('form.factory'),
844
            'content'     => $content,
845
            'page'        => $entity,
846
            'template'    => $template,
847
            'basePath'    => $this->request->getBasePath(),
848
        ]);
849
    }
850
851
    /**
852
     * @param int $objectId
853
     *
854
     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
855
     */
856
    public function abtestAction($objectId)
857
    {
858
        /** @var \Mautic\PageBundle\Model\PageModel $model */
859
        $model  = $this->getModel('page.page');
860
        $entity = $model->getEntity($objectId);
861
862
        if (null != $entity) {
863
            $parent = $entity->getVariantParent();
864
865
            if ($parent || !$this->get('mautic.security')->isGranted('page:pages:create') ||
866
                !$this->get('mautic.security')->hasEntityAccess(
867
                    'page:pages:viewown', 'page:pages:viewother', $entity->getCreatedBy()
868
                )
869
            ) {
870
                return $this->accessDenied();
871
            }
872
873
            $clone = clone $entity;
874
875
            //reset
876
            $clone->setHits(0);
877
            $clone->setRevision(0);
878
            $clone->setVariantHits(0);
879
            $clone->setUniqueHits(0);
880
            $clone->setVariantStartDate(null);
881
            $clone->setIsPublished(false);
882
            $clone->setVariantParent($entity);
883
        }
884
885
        return $this->newAction($clone);
886
    }
887
888
    /**
889
     * Make the variant the main.
890
     *
891
     * @param $objectId
892
     *
893
     * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
894
     */
895
    public function winnerAction($objectId)
896
    {
897
        //todo - add confirmation to button click
898
        $page      = $this->get('session')->get('mautic.page.page', 1);
899
        $returnUrl = $this->generateUrl('mautic_page_index', ['page' => $page]);
900
        $flashes   = [];
901
902
        $postActionVars = [
903
            'returnUrl'       => $returnUrl,
904
            'viewParameters'  => ['page' => $page],
905
            'contentTemplate' => 'MauticPageBundle:Page:index',
906
            'passthroughVars' => [
907
                'activeLink'    => 'mautic_page_index',
908
                'mauticContent' => 'page',
909
            ],
910
        ];
911
912
        if ('POST' == $this->request->getMethod()) {
913
            /** @var \Mautic\PageBundle\Model\PageModel $model */
914
            $model  = $this->getModel('page.page');
915
            $entity = $model->getEntity($objectId);
916
917
            if (null === $entity) {
918
                $flashes[] = [
919
                    'type'    => 'error',
920
                    'msg'     => 'mautic.page.error.notfound',
921
                    'msgVars' => ['%id%' => $objectId],
922
                ];
923
            } elseif (!$this->get('mautic.security')->hasEntityAccess(
924
                'page:pages:editown',
925
                'page:pages:editother',
926
                $entity->getCreatedBy()
927
            )) {
928
                return $this->accessDenied();
929
            } elseif ($model->isLocked($entity)) {
930
                return $this->isLocked($postActionVars, $entity, 'page.page');
931
            }
932
933
            $model->convertVariant($entity);
934
935
            $flashes[] = [
936
                'type'    => 'notice',
937
                'msg'     => 'mautic.page.notice.activated',
938
                'msgVars' => [
939
                    '%name%' => $entity->getTitle(),
940
                    '%id%'   => $objectId,
941
                ],
942
            ];
943
944
            $postActionVars['viewParameters'] = [
945
                'objectAction' => 'view',
946
                'objectId'     => $objectId,
947
            ];
948
            $postActionVars['returnUrl']       = $this->generateUrl('mautic_page_action', $postActionVars['viewParameters']);
949
            $postActionVars['contentTemplate'] = 'MauticPageBundle:Page:view';
950
        } //else don't do anything
951
952
        return $this->postActionRedirect(
953
            array_merge($postActionVars, [
954
                'flashes' => $flashes,
955
            ])
956
        );
957
    }
958
959
    /**
960
     * PreProcess page slots for public view.
961
     *
962
     * @param array $slots
963
     * @param Page  $entity
964
     */
965
    private function processSlots($slots, $entity)
966
    {
967
        /** @var \Mautic\CoreBundle\Templating\Helper\AssetsHelper $assetsHelper */
968
        $assetsHelper = $this->get('templating.helper.assets');
969
        /** @var \Mautic\CoreBundle\Templating\Helper\SlotsHelper $slotsHelper */
970
        $slotsHelper = $this->get('templating.helper.slots');
971
        $formFactory = $this->get('form.factory');
972
973
        $slotsHelper->inBuilder(true);
974
975
        $content = $entity->getContent();
976
977
        foreach ($slots as $slot => $slotConfig) {
978
            // backward compatibility - if slotConfig array does not exist
979
            if (is_numeric($slot)) {
980
                $slot       = $slotConfig;
981
                $slotConfig = [];
982
            }
983
984
            // define default config if does not exist
985
            if (!isset($slotConfig['type'])) {
986
                $slotConfig['type'] = 'html';
987
            }
988
989
            if (!isset($slotConfig['placeholder'])) {
990
                $slotConfig['placeholder'] = 'mautic.page.builder.addcontent';
991
            }
992
993
            $value = isset($content[$slot]) ? $content[$slot] : '';
994
995
            $slotsHelper->set($slot, "<div data-slot=\"text\" id=\"slot-{$slot}\">{$value}</div>");
996
        }
997
998
        $slotsHelper->start('builder'); ?>
999
        <input type="hidden" id="builder_entity_id" value="<?php echo $entity->getSessionId(); ?>"/>
1000
        <?php
1001
        $slotsHelper->stop();
1002
    }
1003
}
1004