Issues (3627)

ReportBundle/Controller/ReportController.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\ReportBundle\Controller;
13
14
use Mautic\CoreBundle\Controller\FormController;
15
use Mautic\CoreBundle\Factory\PageHelperFactoryInterface;
16
use Mautic\CoreBundle\Form\Type\DateRangeType;
17
use Mautic\CoreBundle\Helper\DateTimeHelper;
18
use Mautic\CoreBundle\Helper\InputHelper;
19
use Mautic\ReportBundle\Entity\Report;
20
use Mautic\ReportBundle\Form\Type\DynamicFiltersType;
21
use Mautic\ReportBundle\Model\ExportResponse;
22
use Symfony\Component\HttpFoundation;
23
use Symfony\Component\HttpFoundation\BinaryFileResponse;
24
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
25
26
class ReportController extends FormController
27
{
28
    /**
29
     * @param int $page
30
     *
31
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse|HttpFoundation\Response
32
     */
33
    public function indexAction($page = 1)
34
    {
35
        /* @type \Mautic\ReportBundle\Model\ReportModel $model */
36
        $model = $this->getModel('report');
37
38
        //set some permissions
39
        $permissions = $this->container->get('mautic.security')->isGranted(
40
            [
41
                'report:reports:viewown',
42
                'report:reports:viewother',
43
                'report:reports:create',
44
                'report:reports:editown',
45
                'report:reports:editother',
46
                'report:reports:deleteown',
47
                'report:reports:deleteother',
48
                'report:reports:publishown',
49
                'report:reports:publishother',
50
            ],
51
            'RETURN_ARRAY'
52
        );
53
54
        if (!$permissions['report:reports:viewown'] && !$permissions['report:reports: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.report', $page);
63
64
        $limit  = $pageHelper->getLimit();
65
        $start  = $pageHelper->getStart();
66
        $search = $this->request->get('search', $this->container->get('session')->get('mautic.report.filter', ''));
67
        $filter = ['string' => $search, 'force' => []];
68
        $this->container->get('session')->set('mautic.report.filter', $search);
69
70
        if (!$permissions['report:reports:viewother']) {
71
            $filter['force'][] = ['column' => 'r.createdBy', 'expr' => 'eq', 'value' => $this->user->getId()];
72
        }
73
74
        $orderBy    = $this->container->get('session')->get('mautic.report.orderby', 'r.name');
75
        $orderByDir = $this->container->get('session')->get('mautic.report.orderbydir', 'DESC');
76
        $reports    = $model->getEntities(
77
            [
78
                'start'      => $start,
79
                'limit'      => $limit,
80
                'filter'     => $filter,
81
                'orderBy'    => $orderBy,
82
                'orderByDir' => $orderByDir,
83
            ]
84
        );
85
86
        $count = count($reports);
87
        if ($count && $count < ($start + 1)) {
88
            $lastPage  = $pageHelper->countPage($count);
89
            $returnUrl = $this->generateUrl('mautic_report_index', ['page' => $lastPage]);
90
            $pageHelper->rememberPage($lastPage);
91
92
            return $this->postActionRedirect(
93
                [
94
                    'returnUrl'       => $returnUrl,
95
                    'viewParameters'  => ['page' => $lastPage],
96
                    'contentTemplate' => 'MauticReportBundle:Report:index',
97
                    'passthroughVars' => [
98
                        'activeLink'    => '#mautic_report_index',
99
                        'mauticContent' => 'report',
100
                    ],
101
                ]
102
            );
103
        }
104
105
        $pageHelper->rememberPage($page);
106
107
        return $this->delegateView(
108
            [
109
                'viewParameters' => [
110
                    'searchValue' => $search,
111
                    'items'       => $reports,
112
                    'totalItems'  => $count,
113
                    'page'        => $page,
114
                    'limit'       => $limit,
115
                    'permissions' => $permissions,
116
                    'model'       => $model,
117
                    'tmpl'        => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
118
                    'security'    => $this->container->get('mautic.security'),
119
                ],
120
                'contentTemplate' => 'MauticReportBundle:Report:list.html.php',
121
                'passthroughVars' => [
122
                    'activeLink'    => '#mautic_report_index',
123
                    'mauticContent' => 'report',
124
                    'route'         => $this->generateUrl('mautic_report_index', ['page' => $page]),
125
                ],
126
            ]
127
        );
128
    }
129
130
    /**
131
     * Clone an entity.
132
     *
133
     * @param int $objectId
134
     *
135
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse|HttpFoundation\Response
136
     */
137
    public function cloneAction($objectId)
138
    {
139
        /* @type \Mautic\ReportBundle\Model\ReportModel $model */
140
        $model  = $this->getModel('report');
141
        $entity = $model->getEntity($objectId);
142
143
        if (null != $entity) {
144
            if (!$this->container->get('mautic.security')->isGranted('report:reports:create')
145
                || !$this->container->get('mautic.security')->hasEntityAccess(
146
                    'report:reports:viewown',
147
                    'report:reports:viewother',
148
                    $entity->getCreatedBy()
149
                )
150
            ) {
151
                return $this->accessDenied();
152
            }
153
154
            $entity = clone $entity;
155
            $entity->setId(null);
156
            $entity->setIsPublished(false);
157
        }
158
159
        return $this->newAction($entity);
160
    }
161
162
    /**
163
     * Deletes the entity.
164
     *
165
     * @param $objectId
166
     *
167
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse
168
     */
169
    public function deleteAction($objectId)
170
    {
171
        $page      = $this->container->get('session')->get('mautic.report.page', 1);
172
        $returnUrl = $this->generateUrl('mautic_report_index', ['page' => $page]);
173
        $flashes   = [];
174
175
        $postActionVars = [
176
            'returnUrl'       => $returnUrl,
177
            'viewParameters'  => ['page' => $page],
178
            'contentTemplate' => 'MauticReportBundle:Report:index',
179
            'passthroughVars' => [
180
                'activeLink'    => '#mautic_report_index',
181
                'mauticContent' => 'report',
182
            ],
183
        ];
184
185
        if ('POST' == $this->request->getMethod()) {
186
            /* @type \Mautic\ReportBundle\Model\ReportModel $model */
187
            $model  = $this->getModel('report');
188
            $entity = $model->getEntity($objectId);
189
190
            $check = $this->checkEntityAccess(
191
                $postActionVars,
192
                $entity,
193
                $objectId,
194
                ['report:reports:deleteown', 'report:reports:deleteother'],
195
                $model,
196
                'report'
197
            );
198
            if (true !== $check) {
199
                return $check;
200
            }
201
202
            $model->deleteEntity($entity);
203
204
            $identifier = $this->get('translator')->trans($entity->getName());
205
            $flashes[]  = [
206
                'type'    => 'notice',
207
                'msg'     => 'mautic.core.notice.deleted',
208
                'msgVars' => [
209
                    '%name%' => $identifier,
210
                    '%id%'   => $objectId,
211
                ],
212
            ];
213
        } //else don't do anything
214
215
        return $this->postActionRedirect(
216
            array_merge(
217
                $postActionVars,
218
                [
219
                    'flashes' => $flashes,
220
                ]
221
            )
222
        );
223
    }
224
225
    /**
226
     * Deletes a group of entities.
227
     *
228
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
229
     */
230
    public function batchDeleteAction()
231
    {
232
        $page      = $this->container->get('session')->get('mautic.report.page', 1);
233
        $returnUrl = $this->generateUrl('mautic_report_index', ['page' => $page]);
234
        $flashes   = [];
235
236
        $postActionVars = [
237
            'returnUrl'       => $returnUrl,
238
            'viewParameters'  => ['page' => $page],
239
            'contentTemplate' => 'MauticReportBundle:Report:index',
240
            'passthroughVars' => [
241
                'activeLink'    => '#mautic_report_index',
242
                'mauticContent' => 'report',
243
            ],
244
        ];
245
246
        if ('POST' == $this->request->getMethod()) {
247
            $model     = $this->getModel('report');
248
            $ids       = json_decode($this->request->query->get('ids', '{}'));
249
            $deleteIds = [];
250
251
            // Loop over the IDs to perform access checks pre-delete
252
            foreach ($ids as $objectId) {
253
                $entity = $model->getEntity($objectId);
254
255
                if (null === $entity) {
256
                    $flashes[] = [
257
                        'type'    => 'error',
258
                        'msg'     => 'mautic.report.report.error.notfound',
259
                        'msgVars' => ['%id%' => $objectId],
260
                    ];
261
                } elseif (!$this->container->get('mautic.security')->hasEntityAccess(
262
                    'report:reports:deleteown',
263
                    'report:reports:deleteother',
264
                    $entity->getCreatedBy()
265
                )
266
                ) {
267
                    $flashes[] = $this->accessDenied(true);
268
                } elseif ($model->isLocked($entity)) {
269
                    $flashes[] = $this->isLocked($postActionVars, $entity, 'report', true);
270
                } else {
271
                    $deleteIds[] = $objectId;
272
                }
273
            }
274
275
            // Delete everything we are able to
276
            if (!empty($deleteIds)) {
277
                $entities = $model->deleteEntities($deleteIds);
278
279
                $flashes[] = [
280
                    'type'    => 'notice',
281
                    'msg'     => 'mautic.report.report.notice.batch_deleted',
282
                    'msgVars' => [
283
                        '%count%' => count($entities),
284
                    ],
285
                ];
286
            }
287
        } //else don't do anything
288
289
        return $this->postActionRedirect(
290
            array_merge(
291
                $postActionVars,
292
                [
293
                    'flashes' => $flashes,
294
                ]
295
            )
296
        );
297
    }
298
299
    /**
300
     * Generates edit form and processes post data.
301
     *
302
     * @param int  $objectId   Item ID
303
     * @param bool $ignorePost Flag to ignore POST data
304
     *
305
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse|HttpFoundation\Response
306
     */
307
    public function editAction($objectId, $ignorePost = false)
308
    {
309
        /* @type \Mautic\ReportBundle\Model\ReportModel $model */
310
        $model   = $this->getModel('report');
311
        $entity  = $model->getEntity($objectId);
312
        $session = $this->container->get('session');
313
        $page    = $session->get('mautic.report.page', 1);
314
315
        //set the return URL
316
        $returnUrl = $this->generateUrl('mautic_report_index', ['page' => $page]);
317
318
        $postActionVars = [
319
            'returnUrl'       => $returnUrl,
320
            'viewParameters'  => ['page' => $page],
321
            'contentTemplate' => 'MauticReportBundle:Report:index',
322
            'passthroughVars' => [
323
                'activeLink'    => 'mautic_report_index',
324
                'mauticContent' => 'report',
325
            ],
326
        ];
327
328
        //not found
329
        $check = $this->checkEntityAccess(
330
            $postActionVars,
331
            $entity,
332
            $objectId,
333
            ['report:reports:viewown', 'report:reports:viewother'],
334
            $model,
335
            'report'
336
        );
337
        if (true !== $check) {
338
            return $check;
339
        }
340
341
        //Create the form
342
        $action = $this->generateUrl('mautic_report_action', ['objectAction' => 'edit', 'objectId' => $objectId]);
343
        $form   = $model->createForm($entity, $this->get('form.factory'), $action);
344
345
        ///Check for a submitted form and process it
346
        if (!$ignorePost && 'POST' == $this->request->getMethod()) {
347
            $valid = false;
348
            if (!$cancelled = $this->isFormCancelled($form)) {
349
                // Columns have to be reset in order for Symfony to honor the new submitted order
350
                $oldColumns = $entity->getColumns();
351
                $entity->setColumns([]);
352
353
                $oldGraphs = $entity->getGraphs();
354
                $entity->setGraphs([]);
355
                if ($valid = $this->isFormValid($form)) {
356
                    //form is valid so process the data
357
                    $model->saveEntity($entity, $form->get('buttons')->get('save')->isClicked());
358
359
                    $this->addFlash(
360
                        'mautic.core.notice.updated',
361
                        [
362
                            '%name%'      => $entity->getName(),
363
                            '%menu_link%' => 'mautic_report_index',
364
                            '%url%'       => $this->generateUrl(
365
                                'mautic_report_action',
366
                                [
367
                                    'objectAction' => 'edit',
368
                                    'objectId'     => $entity->getId(),
369
                                ]
370
                            ),
371
                        ]
372
                    );
373
374
                    $returnUrl = $this->generateUrl(
375
                        'mautic_report_view',
376
                        [
377
                            'objectId' => $entity->getId(),
378
                        ]
379
                    );
380
                    $viewParams = ['objectId' => $entity->getId()];
381
                    $template   = 'MauticReportBundle:Report:view';
382
                } else {
383
                    //reset old columns
384
                    $entity->setColumns($oldColumns);
385
                    $entity->setGraphs($oldGraphs);
386
                }
387
            } else {
388
                //unlock the entity
389
                $model->unlockEntity($entity);
390
391
                $returnUrl  = $this->generateUrl('mautic_report_index', ['page' => $page]);
392
                $viewParams = ['report' => $page];
393
                $template   = 'MauticReportBundle:Report:index';
394
            }
395
396
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
397
                // Clear session items in case columns changed
398
                $session->remove('mautic.report.'.$entity->getId().'.orderby');
399
                $session->remove('mautic.report.'.$entity->getId().'.orderbydir');
400
401
                return $this->postActionRedirect(
402
                    array_merge(
403
                        $postActionVars,
404
                        [
405
                            'returnUrl'       => $returnUrl,
406
                            'viewParameters'  => $viewParams,
407
                            'contentTemplate' => $template,
408
                        ]
409
                    )
410
                );
411
            } elseif ($valid) {
412
                // Rebuild the form for updated columns
413
                $form = $model->createForm($entity, $this->get('form.factory'), $action);
414
            }
415
        } else {
416
            //lock the entity
417
            $model->lockEntity($entity);
418
        }
419
420
        return $this->delegateView(
421
            [
422
                'viewParameters' => [
423
                    'report' => $entity,
424
                    'form'   => $this->setFormTheme($form, 'MauticReportBundle:Report:form.html.php', 'MauticReportBundle:FormTheme\Report'),
425
                ],
426
                'contentTemplate' => 'MauticReportBundle:Report:form.html.php',
427
                'passthroughVars' => [
428
                    'activeLink'    => '#mautic_report_index',
429
                    'mauticContent' => 'report',
430
                    'route'         => $this->generateUrl(
431
                        'mautic_report_action',
432
                        [
433
                            'objectAction' => 'edit',
434
                            'objectId'     => $entity->getId(),
435
                        ]
436
                    ),
437
                ],
438
            ]
439
        );
440
    }
441
442
    /**
443
     * Generates new form and processes post data.
444
     *
445
     * @param \Mautic\ReportBundle\Entity\Report|null $entity
446
     *
447
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse|HttpFoundation\Response
448
     */
449
    public function newAction($entity = null)
450
    {
451
        if (!$this->container->get('mautic.security')->isGranted('report:reports:create')) {
452
            return $this->accessDenied();
453
        }
454
455
        /* @type \Mautic\ReportBundle\Model\ReportModel $model */
456
        $model = $this->getModel('report');
457
458
        if (!($entity instanceof Report)) {
459
            /** @var \Mautic\ReportBundle\Entity\Report $entity */
460
            $entity = $model->getEntity();
461
        }
462
463
        $session = $this->container->get('session');
464
        $page    = $session->get('mautic.report.page', 1);
465
466
        $action = $this->generateUrl('mautic_report_action', ['objectAction' => 'new']);
467
        $form   = $model->createForm($entity, $this->get('form.factory'), $action);
468
469
        ///Check for a submitted form and process it
470
        if ('POST' == $this->request->getMethod()) {
471
            $valid = false;
472
            if (!$cancelled = $this->isFormCancelled($form)) {
473
                if ($valid = $this->isFormValid($form)) {
474
                    //form is valid so process the data
475
                    $model->saveEntity($entity);
476
477
                    $this->addFlash(
478
                        'mautic.core.notice.created',
479
                        [
480
                            '%name%'      => $entity->getName(),
481
                            '%menu_link%' => 'mautic_report_index',
482
                            '%url%'       => $this->generateUrl(
483
                                'mautic_report_action',
484
                                [
485
                                    'objectAction' => 'edit',
486
                                    'objectId'     => $entity->getId(),
487
                                ]
488
                            ),
489
                        ]
490
                    );
491
492
                    if (!$form->get('buttons')->get('save')->isClicked()) {
493
                        //return edit view so that all the session stuff is loaded
494
                        return $this->editAction($entity->getId(), true);
495
                    }
496
497
                    $viewParameters = [
498
                        'objectId' => $entity->getId(),
499
                    ];
500
                    $returnUrl = $this->generateUrl('mautic_report_view', $viewParameters);
501
                    $template  = 'MauticReportBundle:Report:view';
502
                }
503
            } else {
504
                $viewParameters = ['page' => $page];
505
                $returnUrl      = $this->generateUrl('mautic_report_index', $viewParameters);
506
                $template       = 'MauticReportBundle:Report:index';
507
            }
508
509
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
510
                return $this->postActionRedirect(
511
                    [
512
                        'returnUrl'       => $returnUrl,
513
                        'viewParameters'  => $viewParameters,
514
                        'contentTemplate' => $template,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.
Loading history...
515
                        'passthroughVars' => [
516
                            'activeLink'    => 'mautic_asset_index',
517
                            'mauticContent' => 'asset',
518
                        ],
519
                    ]
520
                );
521
            }
522
        }
523
524
        return $this->delegateView(
525
            [
526
                'viewParameters' => [
527
                    'report' => $entity,
528
                    'form'   => $this->setFormTheme($form, 'MauticReportBundle:Report:form.html.php', 'MauticReportBundle:FormTheme\Report'),
529
                ],
530
                'contentTemplate' => 'MauticReportBundle:Report:form.html.php',
531
                'passthroughVars' => [
532
                    'activeLink'    => '#mautic_report_index',
533
                    'mauticContent' => 'report',
534
                    'route'         => $this->generateUrl(
535
                        'mautic_report_action',
536
                        [
537
                            'objectAction' => 'new',
538
                        ]
539
                    ),
540
                ],
541
            ]
542
        );
543
    }
544
545
    /**
546
     * Shows a report.
547
     *
548
     * @param int $objectId   Report ID
549
     * @param int $reportPage
550
     *
551
     * @return HttpFoundation\JsonResponse|HttpFoundation\Response
552
     */
553
    public function viewAction($objectId, $reportPage = 1)
554
    {
555
        /* @type \Mautic\ReportBundle\Model\ReportModel $model */
556
        $model    = $this->getModel('report');
557
        $entity   = $model->getEntity($objectId);
558
        $security = $this->container->get('mautic.security');
559
560
        if (null === $entity) {
561
            $page = $this->container->get('session')->get('mautic.report.page', 1);
562
563
            return $this->postActionRedirect(
564
                [
565
                    'returnUrl'       => $this->generateUrl('mautic_report_index', ['page' => $page]),
566
                    'viewParameters'  => ['page' => $page],
567
                    'contentTemplate' => 'MauticReportBundle:Report:index',
568
                    'passthroughVars' => [
569
                        'activeLink'    => '#mautic_report_index',
570
                        'mauticContent' => 'report',
571
                    ],
572
                    'flashes' => [
573
                        [
574
                            'type'    => 'error',
575
                            'msg'     => 'mautic.report.report.error.notfound',
576
                            'msgVars' => ['%id%' => $objectId],
577
                        ],
578
                    ],
579
                ]
580
            );
581
        } elseif (!$security->hasEntityAccess('report:reports:viewown', 'report:reports:viewother', $entity->getCreatedBy())) {
582
            return $this->accessDenied();
583
        }
584
585
        $this->setListFilters();
586
587
        $mysqlFormat = 'Y-m-d';
588
        $session     = $this->container->get('session');
589
590
        // Init the forms
591
        $action = $this->generateUrl('mautic_report_action', ['objectAction' => 'view', 'objectId' => $objectId]);
592
593
        // Get the date range filter values from the request of from the session
594
        $dateRangeValues = $this->request->get('daterange', []);
595
596
        if (!empty($dateRangeValues['date_from'])) {
597
            $from = new \DateTime($dateRangeValues['date_from']);
598
            $session->set('mautic.report.date.from', $from->format($mysqlFormat));
599
        } elseif ($fromDate = $session->get('mautic.report.date.from')) {
600
            $dateRangeValues['date_from'] = $fromDate;
601
        }
602
        if (!empty($dateRangeValues['date_to'])) {
603
            $to = new \DateTime($dateRangeValues['date_to']);
604
            $session->set('mautic.report.date.to', $to->format($mysqlFormat));
605
        } elseif ($toDate = $session->get('mautic.report.date.to')) {
606
            $dateRangeValues['date_to'] = $toDate;
607
        }
608
609
        $dateRangeForm = $this->get('form.factory')->create(DateRangeType::class, $dateRangeValues, ['action' => $action]);
610
        if ('POST' == $this->request->getMethod() && $this->request->request->has('daterange')) {
611
            if ($this->isFormValid($dateRangeForm)) {
612
                $to                         = new \DateTime($dateRangeForm['date_to']->getData());
613
                $dateRangeValues['date_to'] = $to->format($mysqlFormat);
614
                $session->set('mautic.report.date.to', $dateRangeValues['date_to']);
615
616
                $from                         = new \DateTime($dateRangeForm['date_from']->getData());
617
                $dateRangeValues['date_from'] = $from->format($mysqlFormat);
618
                $session->set('mautic.report.date.from', $dateRangeValues['date_from']);
619
            }
620
        }
621
622
        // Setup dynamic filters
623
        $filterDefinitions = $model->getFilterList($entity->getSource());
624
        /** @var array $dynamicFilters */
625
        $dynamicFilters = $session->get('mautic.report.'.$objectId.'.filters', []);
626
        $filterSettings = [];
627
628
        if (count($dynamicFilters) > 0 && count($entity->getFilters()) > 0) {
629
            foreach ($entity->getFilters() as $filter) {
630
                foreach ($dynamicFilters as $dfcol => $dfval) {
631
                    if (1 === $filter['dynamic'] && $filter['column'] === $dfcol) {
632
                        $dynamicFilters[$dfcol]['expr'] = $filter['condition'];
633
                        break;
634
                    }
635
                }
636
            }
637
        }
638
639
        foreach ($dynamicFilters as $filter) {
640
            $filterSettings[$filterDefinitions->definitions[$filter['column']]['alias']] = $filter['value'];
641
        }
642
643
        $dynamicFilterForm = $this->get('form.factory')->create(
644
            DynamicFiltersType::class,
645
            $filterSettings,
646
            [
647
                'action'            => $action,
648
                'report'            => $entity,
649
                'filterDefinitions' => $filterDefinitions,
650
            ]
651
        );
652
653
        $reportData = $model->getReportData(
654
            $entity,
655
            $this->container->get('form.factory'),
656
            [
657
                'dynamicFilters' => $dynamicFilters,
658
                'paginate'       => true,
659
                'reportPage'     => $reportPage,
660
                'dateFrom'       => new \DateTime($dateRangeForm->get('date_from')->getData()),
661
                'dateTo'         => new \DateTime($dateRangeForm->get('date_to')->getData()),
662
            ]
663
        );
664
665
        return $this->delegateView(
666
            [
667
                'viewParameters' => [
668
                    'data'         => $reportData['data'],
669
                    'columns'      => $reportData['columns'],
670
                    'dataColumns'  => $reportData['dataColumns'],
671
                    'totalResults' => $reportData['totalResults'],
672
                    'debug'        => $reportData['debug'],
673
                    'report'       => $entity,
674
                    'reportPage'   => $reportPage,
675
                    'graphs'       => $reportData['graphs'],
676
                    'tmpl'         => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index',
677
                    'limit'        => $reportData['limit'],
678
                    'permissions'  => $security->isGranted(
679
                        [
680
                            'report:reports:viewown',
681
                            'report:reports:viewother',
682
                            'report:reports:create',
683
                            'report:reports:editown',
684
                            'report:reports:editother',
685
                            'report:reports:deleteown',
686
                            'report:reports:deleteother',
687
                        ],
688
                        'RETURN_ARRAY'
689
                    ),
690
                    'dateRangeForm'     => $dateRangeForm->createView(),
691
                    'dynamicFilterForm' => $dynamicFilterForm->createView(),
692
                ],
693
                'contentTemplate' => $reportData['contentTemplate'],
694
                'passthroughVars' => [
695
                    'activeLink'    => '#mautic_report_index',
696
                    'mauticContent' => 'report',
697
                    'route'         => $this->generateUrl(
698
                        'mautic_report_view',
699
                        [
700
                            'objectId'   => $entity->getId(),
701
                            'reportPage' => $reportPage,
702
                        ]
703
                    ),
704
                ],
705
            ]
706
        );
707
    }
708
709
    /**
710
     * Checks access to an entity.
711
     *
712
     * @param object                               $entity
713
     * @param int                                  $objectId
714
     * @param \Mautic\CoreBundle\Model\CommonModel $model
715
     * @param string                               $modelName
716
     *
717
     * @return HttpFoundation\JsonResponse|HttpFoundation\RedirectResponse|void
718
     */
719
    private function checkEntityAccess($postActionVars, $entity, $objectId, array $permissions, $model, $modelName)
720
    {
721
        if (null === $entity) {
722
            return $this->postActionRedirect(
723
                array_merge(
724
                    $postActionVars,
725
                    [
726
                        'flashes' => [
727
                            [
728
                                'type'    => 'error',
729
                                'msg'     => 'mautic.report.report.error.notfound',
730
                                'msgVars' => ['%id%' => $objectId],
731
                            ],
732
                        ],
733
                    ]
734
                )
735
            );
736
        } elseif (!$this->container->get('mautic.security')->hasEntityAccess($permissions[0], $permissions[1], $entity->getCreatedBy())) {
737
            return $this->accessDenied();
738
        } elseif ($model->isLocked($entity)) {
739
            //deny access if the entity is locked
740
            return $this->isLocked($postActionVars, $entity, $modelName);
741
        }
742
743
        return true;
744
    }
745
746
    /**
747
     * @param int    $objectId
748
     * @param string $format
749
     *
750
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
751
     *
752
     * @throws \Exception
753
     */
754
    public function exportAction($objectId, $format = 'csv')
755
    {
756
        /** @var \Mautic\ReportBundle\Model\ReportModel $model */
757
        $model    = $this->getModel('report');
758
        $entity   = $model->getEntity($objectId);
759
        $security = $this->container->get('mautic.security');
760
761
        if (null === $entity) {
762
            $page = $this->container->get('session')->get('mautic.report.page', 1);
763
764
            return $this->postActionRedirect(
765
                [
766
                    'returnUrl'       => $this->generateUrl('mautic_report_index', ['page' => $page]),
767
                    'viewParameters'  => ['page' => $page],
768
                    'contentTemplate' => 'MauticReportBundle:Report:index',
769
                    'passthroughVars' => [
770
                        'activeLink'    => '#mautic_report_index',
771
                        'mauticContent' => 'report',
772
                    ],
773
                    'flashes' => [
774
                        [
775
                            'type'    => 'error',
776
                            'msg'     => 'mautic.report.report.error.notfound',
777
                            'msgVars' => ['%id%' => $objectId],
778
                        ],
779
                    ],
780
                ]
781
            );
782
        } elseif (!$security->hasEntityAccess('report:reports:viewown', 'report:reports:viewother', $entity->getCreatedBy())) {
783
            return $this->accessDenied();
784
        }
785
786
        $session  = $this->get('session');
787
        $fromDate = $session->get('mautic.report.date.from', (new \DateTime('-30 days'))->format('Y-m-d'));
788
        $toDate   = $session->get('mautic.report.date.to', (new \DateTime())->format('Y-m-d'));
789
790
        $date    = (new DateTimeHelper())->toLocalString();
791
        $name    = str_replace(' ', '_', $date).'_'.InputHelper::alphanum($entity->getName(), false, '-');
792
        $options = ['dateFrom' => new \DateTime($fromDate), 'dateTo' => new \DateTime($toDate)];
793
794
        $dynamicFilters            = $session->get('mautic.report.'.$objectId.'.filters', []);
795
        $options['dynamicFilters'] = $dynamicFilters;
796
797
        if ('csv' === $format) {
798
            $response = new HttpFoundation\StreamedResponse(
799
                function () use ($model, $entity, $format, $options) {
800
                    $options['paginate']        = true;
801
                    $options['ignoreGraphData'] = true;
802
                    $options['limit']           = (int) $this->coreParametersHelper->getParameter('report_export_batch_size', 1000);
803
                    $options['page']            = 1;
804
                    $handle                     = fopen('php://output', 'r+');
805
                    do {
806
                        $reportData = $model->getReportData($entity, null, $options);
807
808
                        // Note this so that it's not recalculated on each batch
809
                        $options['totalResults'] = $reportData['totalResults'];
810
811
                        $model->exportResults($format, $entity, $reportData, $handle, $options['page']);
812
                        ++$options['page'];
813
                    } while (!empty($reportData['data']));
814
815
                    fclose($handle);
816
                }
817
            );
818
            $fileName = $name.'.'.$format;
819
            ExportResponse::setResponseHeaders($response, $fileName);
820
        } else {
821
            if ('xlsx' === $format) {
822
                $options['ignoreGraphData'] = true;
823
            }
824
            $reportData = $model->getReportData($entity, null, $options);
825
            $response   = $model->exportResults($format, $entity, $reportData);
826
        }
827
828
        return $response;
829
    }
830
831
    /**
832
     * @param int    $reportId
833
     * @param string $format
834
     *
835
     * @return BinaryFileResponse
836
     *
837
     * @throws \Exception
838
     */
839
    public function downloadAction($reportId, $format = 'csv')
840
    {
841
        if ('csv' !== $format) {
842
            throw new \Exception($this->translator->trans('mautic.format.invalid', ['%format%' => $format, '%validFormats%' => 'csv']));
843
        }
844
845
        /** @var \Mautic\ReportBundle\Model\ReportModel $model */
846
        $model = $this->getModel('report');
847
848
        /** @var \Mautic\ReportBundle\Entity\Report $report */
849
        $report = $model->getEntity($reportId);
850
851
        /** @var \Mautic\CoreBundle\Security\Permissions\CorePermissions $security */
852
        $security = $this->container->get('mautic.security');
853
854
        /** @var \Mautic\ReportBundle\Scheduler\Model\FileHandler $fileHandler */
855
        $fileHandler = $this->container->get('mautic.report.model.file_handler');
856
857
        if (empty($report)) {
858
            return $this->notFound($this->translator->trans('mautic.report.notfound', ['%id%' => $reportId]));
859
        }
860
861
        if (!$security->hasEntityAccess('report:reports:viewown', 'report:reports:viewother', $report->getCreatedBy())) {
862
            return $this->accessDenied();
863
        }
864
865
        if (!$fileHandler->compressedCsvFileForReportExists($report)) {
866
            if ($report->isScheduled()) {
867
                $message = 'mautic.report.download.missing';
868
            } else {
869
                $message = 'mautic.report.download.missing.but.scheduled';
870
                $report->setAsScheduledNow($this->user->getEmail());
871
                $model->saveEntity($report);
872
            }
873
874
            return $this->notFound($this->translator->trans($message, ['%id%' => $reportId]));
875
        }
876
877
        $response = new BinaryFileResponse($fileHandler->getPathToCompressedCsvFileForReport($report));
878
879
        $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, "report-{$report->getId()}.zip");
880
881
        return $response;
882
    }
883
}
884