Issues (3627)

bundles/CoreBundle/Controller/AjaxController.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\CoreBundle\Controller;
13
14
use Mautic\CoreBundle\CoreEvents;
15
use Mautic\CoreBundle\Event\CommandListEvent;
16
use Mautic\CoreBundle\Event\GlobalSearchEvent;
17
use Mautic\CoreBundle\Event\UpgradeEvent;
18
use Mautic\CoreBundle\Helper\CookieHelper;
19
use Mautic\CoreBundle\Helper\InputHelper;
20
use Mautic\CoreBundle\Helper\LanguageHelper;
21
use Mautic\CoreBundle\Helper\PathsHelper;
22
use Mautic\CoreBundle\Helper\UpdateHelper;
23
use Mautic\CoreBundle\IpLookup\AbstractLocalDataLookup;
24
use Mautic\CoreBundle\IpLookup\AbstractLookup;
25
use Mautic\CoreBundle\IpLookup\IpLookupFormInterface;
26
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
27
use Symfony\Bundle\FrameworkBundle\Console\Application;
28
use Symfony\Component\Console\Input\ArgvInput;
29
use Symfony\Component\Console\Output\BufferedOutput;
30
use Symfony\Component\HttpFoundation\JsonResponse;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\PropertyAccess\PropertyAccess;
33
34
/**
35
 * Class AjaxController.
36
 */
37
class AjaxController extends CommonController
38
{
39
    /**
40
     * @param array $dataArray
41
     * @param int   $statusCode
42
     * @param bool  $addIgnoreWdt
43
     *
44
     * @return JsonResponse
45
     *
46
     * @throws \Exception
47
     */
48
    protected function sendJsonResponse($dataArray, $statusCode = null, $addIgnoreWdt = true)
49
    {
50
        $response = new JsonResponse();
51
52
        if ('dev' == $this->container->getParameter('kernel.environment') && $addIgnoreWdt) {
53
            $dataArray['ignore_wdt'] = 1;
54
        }
55
56
        if (null !== $statusCode) {
57
            $response->setStatusCode($statusCode);
58
        }
59
60
        $response->setData($dataArray);
61
62
        return $response;
63
    }
64
65
    /**
66
     * Executes an action requested via ajax.
67
     *
68
     * @return JsonResponse
69
     */
70
    public function delegateAjaxAction()
71
    {
72
        //process ajax actions
73
        $authenticationChecker = $this->get('security.authorization_checker');
74
        $action                = $this->request->get('action');
75
        $bundleName            = null;
76
        if (empty($action)) {
77
            //check POST
78
            $action = $this->request->request->get('action');
79
        }
80
81
        if ($authenticationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
82
            if (false !== strpos($action, ':')) {
83
                //call the specified bundle's ajax action
84
                $parts     = explode(':', $action);
85
                $namespace = 'Mautic';
86
                $isPlugin  = false;
87
88
                if (3 == count($parts) && 'plugin' == $parts['0']) {
89
                    $namespace = 'MauticPlugin';
90
                    array_shift($parts);
91
                    $isPlugin = true;
92
                }
93
94
                if (2 == count($parts)) {
95
                    $bundleName = $parts[0];
96
                    $bundle     = ucfirst($bundleName);
97
                    $action     = $parts[1];
98
                    if (!$classExists = class_exists($namespace.'\\'.$bundle.'Bundle\\Controller\\AjaxController')) {
99
                        // Check if a plugin is prefixed with Mautic
100
                        $bundle      = 'Mautic'.$bundle;
101
                        $classExists = class_exists($namespace.'\\'.$bundle.'Bundle\\Controller\\AjaxController');
102
                    } elseif (!$isPlugin) {
103
                        $bundle = 'Mautic'.$bundle;
104
                    }
105
106
                    if ($classExists) {
107
                        return $this->forward(
108
                            "{$bundle}Bundle:Ajax:executeAjax",
109
                            [
110
                                'action' => $action,
111
                                //forward the request as well as Symfony creates a subrequest without GET/POST
112
                                'request' => $this->request,
113
                                'bundle'  => $bundleName,
114
                            ]
115
                        );
116
                    }
117
                }
118
            }
119
120
            return $this->executeAjaxAction($action, $this->request, $bundleName);
121
        }
122
123
        return $this->sendJsonResponse(['success' => 0]);
124
    }
125
126
    /**
127
     * @param      $action
128
     * @param null $bundle
129
     *
130
     * @return JsonResponse
131
     */
132
    public function executeAjaxAction($action, Request $request, $bundle = null)
133
    {
134
        if (method_exists($this, "{$action}Action")) {
135
            return $this->{"{$action}Action"}($request, $bundle);
136
        }
137
138
        return $this->sendJsonResponse(['success' => 0]);
139
    }
140
141
    /**
142
     * @return JsonResponse
143
     */
144
    protected function globalSearchAction(Request $request)
145
    {
146
        $dataArray = ['success' => 1];
147
        $searchStr = InputHelper::clean($request->query->get('global_search', ''));
148
        $this->get('session')->set('mautic.global_search', $searchStr);
149
150
        $event = new GlobalSearchEvent($searchStr, $this->get('translator'));
151
        $this->get('event_dispatcher')->dispatch(CoreEvents::GLOBAL_SEARCH, $event);
152
153
        $dataArray['newContent'] = $this->renderView(
154
            'MauticCoreBundle:GlobalSearch:results.html.php',
155
            ['results' => $event->getResults()]
156
        );
157
158
        return $this->sendJsonResponse($dataArray);
159
    }
160
161
    /**
162
     * @return JsonResponse
163
     */
164
    protected function commandListAction(Request $request)
165
    {
166
        $model      = InputHelper::clean($request->query->get('model'));
167
        $commands   = $this->getModel($model)->getCommandList();
168
        $dataArray  = [];
169
        $translator = $this->get('translator');
170
        foreach ($commands as $k => $c) {
171
            if (is_array($c)) {
172
                foreach ($c as $subc) {
173
                    $command = $translator->trans($k);
174
                    $command = (false === strpos($command, ':')) ? $command.':' : $command;
175
176
                    $dataArray[$command.$translator->trans($subc)] = ['value' => $command.$translator->trans($subc)];
177
                }
178
            } else {
179
                $command = $translator->trans($c);
180
                $command = (false === strpos($command, ':')) ? $command.':' : $command;
181
182
                $dataArray[$command] = ['value' => $command];
183
            }
184
        }
185
        sort($dataArray);
186
187
        return $this->sendJsonResponse($dataArray);
188
    }
189
190
    /**
191
     * @return JsonResponse
192
     */
193
    protected function globalCommandListAction(Request $request)
194
    {
195
        $dispatcher = $this->get('event_dispatcher');
196
        $event      = new CommandListEvent();
197
        $dispatcher->dispatch(CoreEvents::BUILD_COMMAND_LIST, $event);
198
        $allCommands = $event->getCommands();
199
        $translator  = $this->get('translator');
200
        $dataArray   = [];
201
        $dupChecker  = [];
202
        foreach ($allCommands as $commands) {
203
            //@todo if/when figure out a way for typeahead dynamic headers
204
            //$header = $translator->trans($header);
205
            //$dataArray[$header] = array();
206
            foreach ($commands as $k => $c) {
207
                if (is_array($c)) {
208
                    $command = $translator->trans($k);
209
                    $command = (false === strpos($command, ':')) ? $command.':' : $command;
210
211
                    foreach ($c as $subc) {
212
                        $subcommand = $command.$translator->trans($subc);
213
                        if (!in_array($subcommand, $dupChecker)) {
214
                            $dataArray[]  = ['value' => $subcommand];
215
                            $dupChecker[] = $subcommand;
216
                        }
217
                    }
218
                } else {
219
                    $command = $translator->trans($k);
220
                    $command = (false === strpos($command, ':')) ? $command.':' : $command;
221
222
                    if (!in_array($command, $dupChecker)) {
223
                        $dataArray[]  = ['value' => $command];
224
                        $dupChecker[] = $command;
225
                    }
226
                }
227
            }
228
            //sort($dataArray[$header]);
229
        }
230
        //ksort($dataArray);
231
        sort($dataArray);
232
233
        return $this->sendJsonResponse($dataArray);
234
    }
235
236
    /**
237
     * @return JsonResponse
238
     */
239
    protected function togglePublishStatusAction(Request $request)
240
    {
241
        $dataArray      = ['success' => 0];
242
        $name           = InputHelper::clean($request->request->get('model'));
243
        $id             = InputHelper::clean($request->request->get('id'));
244
        $customToggle   = InputHelper::clean($request->request->get('customToggle'));
245
        $model          = $this->getModel($name);
246
247
        $post = $request->request->all();
248
        unset($post['model'], $post['id'], $post['action']);
249
        if (!empty($post)) {
250
            $extra = http_build_query($post);
251
        } else {
252
            $extra = '';
253
        }
254
255
        $entity = $model->getEntity($id);
256
        if (null !== $entity) {
257
            $permissionBase = $model->getPermissionBase();
258
259
            /** @var CorePermissions $security */
260
            $security  = $this->get('mautic.security');
261
            $createdBy = (method_exists($entity, 'getCreatedBy')) ? $entity->getCreatedBy() : null;
262
263
            if ($security->checkPermissionExists($permissionBase.':publishown')) {
264
                $hasPermission = $security->hasEntityAccess($permissionBase.':publishown', $permissionBase.':publishother', $createdBy);
265
            } elseif ($security->checkPermissionExists($permissionBase.':publish')) {
266
                $hasPermission = $security->isGranted($permissionBase.':publish');
267
            } elseif ($security->checkPermissionExists($permissionBase.':manage')) {
268
                $hasPermission = $security->isGranted($permissionBase.':manage');
269
            } elseif ($security->checkPermissionExists($permissionBase.':full')) {
270
                $hasPermission = $security->isGranted($permissionBase.':full');
271
            } elseif ($security->checkPermissionExists($permissionBase.':editown')) {
272
                $hasPermission = $security->hasEntityAccess($permissionBase.':editown', $permissionBase.':editother', $createdBy);
273
            } elseif ($security->checkPermissionExists($permissionBase.':edit')) {
274
                $hasPermission = $security->isGranted($permissionBase.':edit');
275
            } else {
276
                $hasPermission = false;
277
            }
278
279
            if ($hasPermission) {
280
                $dataArray['success'] = 1;
281
                //toggle permission state
282
                if ($customToggle) {
283
                    $accessor = PropertyAccess::createPropertyAccessor();
284
                    $accessor->setValue($entity, $customToggle, !$accessor->getValue($entity, $customToggle));
285
                    $model->getRepository()->saveEntity($entity);
286
                } else {
287
                    $refresh = $model->togglePublishStatus($entity);
0 ignored issues
show
The method togglePublishStatus() does not exist on Mautic\CoreBundle\Model\AbstractCommonModel. It seems like you code against a sub-type of Mautic\CoreBundle\Model\AbstractCommonModel such as Mautic\CoreBundle\Model\FormModel. ( Ignorable by Annotation )

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

287
                    /** @scrutinizer ignore-call */ 
288
                    $refresh = $model->togglePublishStatus($entity);
Loading history...
288
                }
289
                if (!empty($refresh)) {
290
                    $dataArray['reload'] = 1;
291
                } else {
292
                    //get updated icon HTML
293
                    $html = $this->renderView(
294
                        'MauticCoreBundle:Helper:publishstatus_icon.html.php',
295
                        [
296
                            'item'  => $entity,
297
                            'model' => $name,
298
                            'query' => $extra,
299
                            'size'  => (isset($post['size'])) ? $post['size'] : '',
300
                        ]
301
                    );
302
                    $dataArray['statusHtml'] = $html;
303
                }
304
            }
305
        }
306
307
        $dataArray['flashes'] = $this->getFlashContent();
308
309
        return $this->sendJsonResponse($dataArray);
310
    }
311
312
    /**
313
     * Unlock an entity locked by the current user.
314
     *
315
     * @return JsonResponse
316
     */
317
    protected function unlockEntityAction(Request $request)
318
    {
319
        $dataArray   = ['success' => 0];
320
        $name        = InputHelper::clean($request->request->get('model'));
321
        $id          = (int) $request->request->get('id');
322
        $extra       = InputHelper::clean($request->request->get('parameter'));
323
        $model       = $this->getModel($name);
324
        $entity      = $model->getEntity($id);
325
        $currentUser = $this->user;
326
327
        if (method_exists($entity, 'getCheckedOutBy')) {
328
            $checkedOut = $entity->getCheckedOutBy();
329
            if (null !== $entity && !empty($checkedOut) && $checkedOut === $currentUser->getId()) {
330
                //entity exists, is checked out, and is checked out by the current user so go ahead and unlock
331
                $model->unlockEntity($entity, $extra);
332
                $dataArray['success'] = 1;
333
            }
334
        }
335
336
        return $this->sendJsonResponse($dataArray);
337
    }
338
339
    /**
340
     * Sets the page layout to the update layout.
341
     *
342
     * @return JsonResponse
343
     */
344
    protected function updateSetUpdateLayoutAction(Request $request)
345
    {
346
        $dataArray = [
347
            'success' => 1,
348
            'content' => $this->renderView('MauticCoreBundle:Update:update.html.php'),
349
        ];
350
351
        // A way to keep the upgrade from failing if the session is lost after
352
        // the cache is cleared by upgrade.php
353
        /** @var \Mautic\CoreBundle\Helper\CookieHelper $cookieHelper */
354
        $cookieHelper = $this->container->get('mautic.helper.cookie');
355
        $cookieHelper->setCookie('mautic_update', 'setupUpdate', 300);
356
357
        return $this->sendJsonResponse($dataArray);
358
    }
359
360
    /**
361
     * Downloads the update package.
362
     *
363
     * @return JsonResponse
364
     */
365
    protected function updateDownloadPackageAction(Request $request)
366
    {
367
        $dataArray  = ['success' => 0];
368
        $translator = $this->translator;
369
370
        /** @var \Mautic\CoreBundle\Helper\UpdateHelper $updateHelper */
371
        $updateHelper = $this->container->get('mautic.helper.update');
372
373
        // Fetch the update package
374
        $update  = $updateHelper->fetchData();
375
        $package = $updateHelper->fetchPackage($update['package']);
376
377
        /** @var \Mautic\CoreBundle\Helper\CookieHelper $cookieHelper */
378
        $cookieHelper = $this->container->get('mautic.helper.cookie');
379
380
        if ($package['error']) {
381
            $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed');
382
            $dataArray['message']    = $translator->trans('mautic.core.update.error', ['%error%' => $translator->trans($package['message'])]);
383
384
            // A way to keep the upgrade from failing if the session is lost after
385
            // the cache is cleared by upgrade.php
386
            $cookieHelper->deleteCookie('mautic_update');
387
        } else {
388
            $dataArray['success']        = 1;
389
            $dataArray['stepStatus']     = $translator->trans('mautic.core.update.step.success');
390
            $dataArray['nextStep']       = $translator->trans('mautic.core.update.step.extracting.package');
391
            $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress');
392
393
            // A way to keep the upgrade from failing if the session is lost after
394
            // the cache is cleared by upgrade.php
395
            $cookieHelper->setCookie('mautic_update', 'downloadPackage', 300);
396
        }
397
398
        return $this->sendJsonResponse($dataArray);
399
    }
400
401
    /**
402
     * Extracts the update package.
403
     *
404
     * @return JsonResponse
405
     */
406
    protected function updateExtractPackageAction(Request $request)
407
    {
408
        $dataArray  = ['success' => 0];
409
        $translator = $this->translator;
410
411
        /** @var UpdateHelper $updateHelper */
412
        $updateHelper = $this->container->get('mautic.helper.update');
413
414
        /** @var CookieHelper $cookieHelper */
415
        $cookieHelper = $this->container->get('mautic.helper.cookie');
416
417
        /** @var PathsHelper $pathsHelper */
418
        $pathsHelper = $this->container->get('mautic.helper.paths');
419
420
        // Fetch the package data
421
        $update  = $updateHelper->fetchData();
422
        $zipFile = $pathsHelper->getSystemPath('cache').'/'.basename($update['package']);
423
424
        $zipper  = new \ZipArchive();
425
        $archive = $zipper->open($zipFile);
426
427
        if (true !== $archive) {
428
            // Get the exact error
429
            switch ($archive) {
430
                case \ZipArchive::ER_EXISTS:
431
                    $error = 'mautic.core.update.archive_file_exists';
432
                    break;
433
                case \ZipArchive::ER_INCONS:
434
                case \ZipArchive::ER_INVAL:
435
                case \ZipArchive::ER_MEMORY:
436
                    $error = 'mautic.core.update.archive_zip_corrupt';
437
                    break;
438
                case \ZipArchive::ER_NOENT:
439
                    $error = 'mautic.core.update.archive_no_such_file';
440
                    break;
441
                case \ZipArchive::ER_NOZIP:
442
                    $error = 'mautic.core.update.archive_not_valid_zip';
443
                    break;
444
                case \ZipArchive::ER_READ:
445
                case \ZipArchive::ER_SEEK:
446
                case \ZipArchive::ER_OPEN:
447
                default:
448
                    $error = 'mautic.core.update.archive_could_not_open';
449
                    break;
450
            }
451
452
            $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed');
453
            $dataArray['message']    = $translator->trans('mautic.core.update.error', ['%error%' => $translator->trans($error)]);
454
455
            // A way to keep the upgrade from failing if the session is lost after
456
            // the cache is cleared by upgrade.php
457
            $cookieHelper->deleteCookie('mautic_update');
458
        } else {
459
            // Extract the archive file now
460
            if (!$zipper->extractTo(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade')) {
461
                $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed');
462
                $dataArray['message']    = $translator->trans(
463
                    'mautic.core.update.error',
464
                    ['%error%' => $translator->trans('mautic.core.update.error_extracting_package')]
465
                );
466
            } else {
467
                $zipper->close();
468
469
                $dataArray['success']        = 1;
470
                $dataArray['stepStatus']     = $translator->trans('mautic.core.update.step.success');
471
                $dataArray['nextStep']       = $translator->trans('mautic.core.update.step.moving.package');
472
                $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress');
473
474
                // A way to keep the upgrade from failing if the session is lost after
475
                // the cache is cleared by upgrade.php
476
                $cookieHelper->setCookie('mautic_update', 'extractPackage', 300);
477
            }
478
        }
479
480
        return $this->sendJsonResponse($dataArray);
481
    }
482
483
    /**
484
     * Migrate the database to the latest version.
485
     *
486
     * @return JsonResponse
487
     */
488
    public function updateDatabaseMigrationAction(Request $request)
489
    {
490
        $dataArray  = ['success' => 0];
491
        $translator = $this->translator;
492
        $result     = 0;
493
494
        // Also do the last bit of filesystem cleanup from the upgrade here
495
        if (is_dir(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade')) {
496
            $iterator = new \FilesystemIterator(
497
                dirname($this->container->getParameter('kernel.root_dir')).'/upgrade', \FilesystemIterator::SKIP_DOTS
498
            );
499
500
            /** @var \FilesystemIterator $file */
501
            foreach ($iterator as $file) {
502
                // Sanity checks
503
                if ($file->isFile()) {
504
                    @unlink($file->getPath().'/'.$file->getFilename());
505
                }
506
            }
507
508
            // Should be empty now, nuke the folder
509
            @rmdir(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade');
510
        }
511
512
        $cacheDir = $this->container->get('mautic.helper.paths')->getSystemPath('cache');
513
514
        // Cleanup the update cache data now too
515
        if (file_exists($cacheDir.'/lastUpdateCheck.txt')) {
516
            @unlink($cacheDir.'/lastUpdateCheck.txt');
517
        }
518
519
        if (file_exists($cacheDir.'/'.MAUTIC_VERSION.'.zip')) {
520
            @unlink($cacheDir.'/'.MAUTIC_VERSION.'.zip');
521
        }
522
523
        // Update languages
524
        /** @var LanguageHelper $languageHelper */
525
        $languageHelper     = $this->container->get('mautic.helper.language');
526
        $supportedLanguages = $languageHelper->getSupportedLanguages();
527
528
        // If there is only one language, assume it is 'en_US' and skip this
529
        if (count($supportedLanguages) > 1) {
530
            // First, update the cached language data
531
            $result = $languageHelper->fetchLanguages(true);
532
533
            // Only continue if not in error
534
            if (!isset($result['error'])) {
535
                foreach ($supportedLanguages as $locale => $name) {
536
                    // We don't need to update en_US, that comes with the main package
537
                    if ('en_US' == $locale) {
538
                        continue;
539
                    }
540
541
                    // Update time
542
                    $extractResult = $languageHelper->extractLanguagePackage($locale);
543
544
                    if ($extractResult['error']) {
545
                        // TODO - Need to look at adding messages during update...
546
                    }
547
                }
548
            }
549
        }
550
551
        $iterator = new \FilesystemIterator($this->container->getParameter('kernel.root_dir').'/migrations', \FilesystemIterator::SKIP_DOTS);
552
553
        if (iterator_count($iterator)) {
554
            $args = ['console', 'doctrine:migrations:migrate', '--no-interaction', '--env='.MAUTIC_ENV];
555
556
            if ('prod' === MAUTIC_ENV) {
557
                $args[] = '--no-debug';
558
            }
559
560
            $input       = new ArgvInput($args);
561
            $application = new Application($this->container->get('kernel'));
562
            $application->setAutoExit(false);
563
            $output = new BufferedOutput();
564
565
            $minExecutionTime = 300;
566
            $maxExecutionTime = (int) ini_get('max_execution_time');
567
            if ($maxExecutionTime > 0 && $maxExecutionTime < $minExecutionTime) {
568
                ini_set('max_execution_time', $minExecutionTime);
569
            }
570
571
            $result = $application->run($input, $output);
572
        }
573
574
        /** @var CookieHelper $cookieHelper */
575
        $cookieHelper = $this->container->get('mautic.helper.cookie');
576
577
        if (0 !== $result) {
578
            // Log the output
579
            $outputBuffer = trim(preg_replace('/\n\s*\n/s', ' \\ ', $output->fetch()));
580
            $outputBuffer = preg_replace('/\s\s+/', ' ', trim($outputBuffer));
581
            $this->container->get('monolog.logger.mautic')->log('error', '[UPGRADE ERROR] Exit code '.$result.'; '.$outputBuffer);
582
583
            $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed');
584
            $dataArray['message']    = $translator->trans(
585
                    'mautic.core.update.error',
586
                    ['%error%' => $translator->trans('mautic.core.update.error_performing_migration')]
587
                ).' <a href="'.$this->generateUrl('mautic_core_update_schema', ['update' => 1])
588
                .'" class="btn btn-primary btn-xs" data-toggle="ajax">'.$translator->trans('mautic.core.retry').'</a>';
589
590
            // A way to keep the upgrade from failing if the session is lost after
591
            // the cache is cleared by upgrade.php
592
            $cookieHelper->deleteCookie('mautic_update');
593
        } else {
594
            // A way to keep the upgrade from failing if the session is lost after
595
            // the cache is cleared by upgrade.php
596
            /* @var CookieHelper $cookieHelper */
597
            $cookieHelper->setCookie('mautic_update', 'schemaMigration', 300);
598
599
            if ($request->get('finalize', false)) {
600
                // Go to the finalize step
601
                $dataArray['success']        = 1;
602
                $dataArray['stepStatus']     = $translator->trans('mautic.core.update.step.success');
603
                $dataArray['nextStep']       = $translator->trans('mautic.core.update.step.finalizing');
604
                $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress');
605
            } else {
606
                // Upgrading from 1.0.5
607
608
                return $this->updateFinalizationAction($request);
609
            }
610
        }
611
612
        return $this->sendJsonResponse($dataArray);
613
    }
614
615
    /**
616
     * Finalize update.
617
     *
618
     * @return JsonResponse
619
     */
620
    public function updateFinalizationAction(Request $request)
621
    {
622
        $dataArray  = ['success' => 0];
623
        $translator = $this->translator;
624
625
        // Here as a just in case it's needed for a future upgrade
626
        $dataArray['success'] = 1;
627
        $dataArray['message'] = $translator->trans('mautic.core.update.update_successful', ['%version%' => $this->factory->getVersion()]);
628
629
        // Check for a post install message
630
        if ($postMessage = $this->container->get('session')->get('post_upgrade_message', false)) {
631
            $this->container->get('session')->remove('post_upgrade_message');
632
            $postMessage              = sprintf('<h4 class="mt-lg">%s</h4><p>%s</p>', $this->container->get('translator')->trans('mautic.core.update.post_message'), $postMessage);
633
            $dataArray['postmessage'] = $postMessage;
634
        }
635
636
        // Execute the mautic.post_upgrade event
637
        $this->dispatcher->dispatch(CoreEvents::POST_UPGRADE, new UpgradeEvent($dataArray));
638
639
        // A way to keep the upgrade from failing if the session is lost after
640
        // the cache is cleared by upgrade.php
641
        /** @var CookieHelper $cookieHelper */
642
        $cookieHelper = $this->container->get('mautic.helper.cookie');
643
        $cookieHelper->deleteCookie('mautic_update');
644
645
        // Set a redirect to force a page reload to get new menu items, assets, etc
646
        $dataArray['redirect'] = $this->container->get('router')->generate('mautic_core_update');
647
648
        return $this->sendJsonResponse($dataArray);
649
    }
650
651
    /**
652
     * @return JsonResponse
653
     */
654
    protected function clearNotificationAction(Request $request)
655
    {
656
        $id = (int) $request->get('id', 0);
657
658
        /** @var \Mautic\CoreBundle\Model\NotificationModel $model */
659
        $model = $this->getModel('core.notification');
660
        $model->clearNotification($id, 200);
661
662
        return $this->sendJsonResponse(['success' => 1]);
663
    }
664
665
    /**
666
     * @return JsonResponse
667
     */
668
    protected function getBuilderTokensAction(Request $request)
669
    {
670
        $tokens = [];
671
672
        if (method_exists($this, 'getBuilderTokens')) {
673
            $query  = $request->get('query');
674
            $tokens = $this->getBuilderTokens($query);
675
        }
676
677
        return $this->sendJsonResponse($tokens);
678
    }
679
680
    /**
681
     * Fetch remote data store.
682
     *
683
     * @return JsonResponse
684
     */
685
    protected function downloadIpLookupDataStoreAction(Request $request)
686
    {
687
        $dataArray = ['success' => 0];
688
689
        if ($request->request->has('service')) {
690
            $serviceName = $request->request->get('service');
691
            $serviceAuth = $request->request->get('auth');
692
693
            /** @var \Mautic\CoreBundle\Factory\IpLookupFactory $ipServiceFactory */
694
            $ipServiceFactory = $this->container->get('mautic.ip_lookup.factory');
695
            $ipService        = $ipServiceFactory->getService($serviceName, $serviceAuth);
696
697
            if ($ipService instanceof AbstractLocalDataLookup) {
698
                if ($ipService->downloadRemoteDataStore()) {
699
                    $dataArray['success'] = 1;
700
                    $dataArray['message'] = $this->container->get('translator')->trans('mautic.core.success');
701
                } else {
702
                    $remoteUrl = $ipService->getRemoteDateStoreDownloadUrl();
703
                    $localPath = $ipService->getLocalDataStoreFilepath();
704
705
                    if ($remoteUrl && $localPath) {
706
                        $dataArray['error'] = $this->container->get('translator')->trans(
707
                            'mautic.core.ip_lookup.remote_fetch_error',
708
                            [
709
                                '%remoteUrl%' => $remoteUrl,
710
                                '%localPath%' => $localPath,
711
                            ]
712
                        );
713
                    } else {
714
                        $dataArray['error'] = $this->container->get('translator')->trans(
715
                            'mautic.core.ip_lookup.remote_fetch_error_generic'
716
                        );
717
                    }
718
                }
719
            }
720
        }
721
722
        return $this->sendJsonResponse($dataArray);
723
    }
724
725
    /**
726
     * Fetch IP Lookup form.
727
     *
728
     * @return JsonResponse
729
     */
730
    protected function getIpLookupFormAction(Request $request)
731
    {
732
        $dataArray = ['html' => '', 'attribution' => ''];
733
734
        if ($request->request->has('service')) {
735
            $serviceName = $request->request->get('service');
736
737
            /** @var \Mautic\CoreBundle\Factory\IpLookupFactory $ipServiceFactory */
738
            $ipServiceFactory = $this->container->get('mautic.ip_lookup.factory');
739
            $ipService        = $ipServiceFactory->getService($serviceName);
740
741
            if ($ipService instanceof AbstractLookup) {
742
                $dataArray['attribution'] = $ipService->getAttribution();
743
                if ($ipService instanceof IpLookupFormInterface) {
744
                    if ($formType = $ipService->getConfigFormService()) {
745
                        $themes   = $ipService->getConfigFormThemes();
746
                        $themes[] = 'MauticCoreBundle:FormTheme\Config';
747
748
                        $form = $this->get('form.factory')->create($formType, [], ['ip_lookup_service' => $ipService]);
749
                        $html = $this->renderView(
750
                            'MauticCoreBundle:FormTheme\Config:ip_lookup_config_row.html.php',
751
                            [
752
                                'form' => $this->setFormTheme($form, 'MauticCoreBundle:FormTheme\Config:ip_lookup_config_row.html.php', $themes),
753
                            ]
754
                        );
755
756
                        $html              = str_replace($formType.'_', 'config_coreconfig_ip_lookup_config_', $html);
757
                        $html              = str_replace($formType, 'config[coreconfig][ip_lookup_config]', $html);
758
                        $dataArray['html'] = $html;
759
                    }
760
                }
761
            }
762
        }
763
764
        return $this->sendJsonResponse($dataArray);
765
    }
766
}
767