Issues (3627)

ReportBundle/Controller/ReportController.php (8 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\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,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $viewParams does not seem to be defined for all execution paths leading up to this point.
Loading history...
407
                            '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...
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(
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

477
                    /** @scrutinizer ignore-deprecated */ $this->addFlash(

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...
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,
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...
513
                        '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...
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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type Symfony\Component\HttpFo...dation\RedirectResponse.
Loading history...
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(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->postAction...%id%' => $objectId))))) returns the type Symfony\Component\HttpFo...dation\RedirectResponse which is incompatible with the documented return type Symfony\Component\HttpFoundation\StreamedResponse.
Loading history...
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