Issues (3627)

bundles/UserBundle/Controller/UserController.php (2 issues)

1
<?php
2
3
/*
4
 * @copyright   2014 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\UserBundle\Controller;
13
14
use Mautic\CoreBundle\Controller\FormController;
15
use Mautic\CoreBundle\Factory\PageHelperFactoryInterface;
16
use Mautic\CoreBundle\Helper\InputHelper;
17
use Mautic\CoreBundle\Helper\LanguageHelper;
18
use Mautic\UserBundle\Form\Type\ContactType;
19
20
class UserController extends FormController
21
{
22
    /**
23
     * Generate's default user list.
24
     *
25
     * @param int $page
26
     *
27
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
28
     */
29
    public function indexAction($page = 1)
30
    {
31
        if (!$this->get('mautic.security')->isGranted('user:users:view')) {
32
            return $this->accessDenied();
33
        }
34
35
        /** @var PageHelperFactoryInterface $pageHelperFacotry */
36
        $pageHelperFacotry = $this->get('mautic.page.helper.factory');
37
        $pageHelper        = $pageHelperFacotry->make('mautic.user', $page);
38
39
        $this->setListFilters();
40
41
        $limit      = $pageHelper->getLimit();
42
        $start      = $pageHelper->getStart();
43
        $orderBy    = $this->get('session')->get('mautic.user.orderby', 'u.lastName, u.firstName, u.username');
44
        $orderByDir = $this->get('session')->get('mautic.user.orderbydir', 'ASC');
45
        $search     = $this->request->get('search', $this->get('session')->get('mautic.user.filter', ''));
46
        $search     = html_entity_decode($search);
47
        $this->get('session')->set('mautic.user.filter', $search);
48
49
        //do some default filtering
50
        $filter = ['string' => $search, 'force' => ''];
51
        $tmpl   = $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index';
52
        $users  = $this->getModel('user.user')->getEntities(
53
            [
54
                'start'      => $start,
55
                'limit'      => $limit,
56
                'filter'     => $filter,
57
                'orderBy'    => $orderBy,
58
                'orderByDir' => $orderByDir,
59
            ]);
60
61
        //Check to see if the number of pages match the number of users
62
        $count = count($users);
63
        if ($count && $count < ($start + 1)) {
64
            //the number of entities are now less then the current page so redirect to the last page
65
            $lastPage = $pageHelper->countPage($count);
66
            $pageHelper->rememberPage($lastPage);
67
            $returnUrl = $this->generateUrl('mautic_user_index', ['page' => $lastPage]);
68
69
            return $this->postActionRedirect([
70
                'returnUrl'      => $returnUrl,
71
                'viewParameters' => [
72
                    'page' => $lastPage,
73
                    'tmpl' => $tmpl,
74
                ],
75
                'contentTemplate' => 'MauticUserBundle:User:index',
76
                'passthroughVars' => [
77
                    'activeLink'    => '#mautic_user_index',
78
                    'mauticContent' => 'user',
79
                ],
80
            ]);
81
        }
82
83
        $pageHelper->rememberPage($page);
84
85
        return $this->delegateView([
86
            'viewParameters'  => [
87
                'items'       => $users,
88
                'searchValue' => $search,
89
                'page'        => $page,
90
                'limit'       => $limit,
91
                'tmpl'        => $tmpl,
92
                'permissions' => [
93
                    'create' => $this->get('mautic.security')->isGranted('user:users:create'),
94
                    'edit'   => $this->get('mautic.security')->isGranted('user:users:editother'),
95
                    'delete' => $this->get('mautic.security')->isGranted('user:users:deleteother'),
96
                ],
97
            ],
98
            'contentTemplate' => 'MauticUserBundle:User:list.html.php',
99
            'passthroughVars' => [
100
                'route'         => $this->generateUrl('mautic_user_index', ['page' => $page]),
101
                'mauticContent' => 'user',
102
            ],
103
        ]);
104
    }
105
106
    /**
107
     * Generate's form and processes new post data.
108
     *
109
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
110
     */
111
    public function newAction()
112
    {
113
        if (!$this->get('mautic.security')->isGranted('user:users:create')) {
114
            return $this->accessDenied();
115
        }
116
117
        /** @var \Mautic\UserBundle\Model\UserModel $model */
118
        $model = $this->getModel('user.user');
119
120
        //retrieve the user entity
121
        $user = $model->getEntity();
122
123
        //set the return URL for post actions
124
        $returnUrl = $this->generateUrl('mautic_user_index');
125
126
        //set the page we came from
127
        $page = $this->get('session')->get('mautic.user.page', 1);
128
129
        //get the user form factory
130
        $action = $this->generateUrl('mautic_user_action', ['objectAction' => 'new']);
131
        $form   = $model->createForm($user, $this->get('form.factory'), $action);
132
133
        //Check for a submitted form and process it
134
        if ('POST' == $this->request->getMethod()) {
135
            $valid = false;
136
            if (!$cancelled = $this->isFormCancelled($form)) {
137
                //check to see if the password needs to be rehashed
138
                $formUser          = $this->request->request->get('user', []);
139
                $submittedPassword = $formUser['plainPassword']['password'] ?? null;
140
                $encoder           = $this->get('security.encoder_factory')->getEncoder($user);
141
                $password          = $model->checkNewPassword($user, $encoder, $submittedPassword);
142
143
                if ($valid = $this->isFormValid($form)) {
144
                    //form is valid so process the data
145
                    $user->setPassword($password);
146
                    $model->saveEntity($user);
147
148
                    //check if the user's locale has been downloaded already, fetch it if not
149
                    /** @var LanguageHelper $languageHelper */
150
                    $languageHelper     = $this->container->get('mautic.helper.language');
151
                    $installedLanguages = $languageHelper->getSupportedLanguages();
152
153
                    if ($user->getLocale() && !array_key_exists($user->getLocale(), $installedLanguages)) {
154
                        $fetchLanguage = $languageHelper->extractLanguagePackage($user->getLocale());
155
156
                        // If there is an error, we need to reset the user's locale to the default
157
                        if ($fetchLanguage['error']) {
158
                            $user->setLocale(null);
159
                            $model->saveEntity($user);
160
                            $message     = 'mautic.core.could.not.set.language';
161
                            $messageVars = [];
162
163
                            if (isset($fetchLanguage['message'])) {
164
                                $message = $fetchLanguage['message'];
165
                            }
166
167
                            if (isset($fetchLanguage['vars'])) {
168
                                $messageVars = $fetchLanguage['vars'];
169
                            }
170
171
                            $this->addFlash($message, $messageVars);
172
                        }
173
                    }
174
175
                    $this->addFlash('mautic.core.notice.created', [
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

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

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...
176
                        '%name%'      => $user->getName(),
177
                        '%menu_link%' => 'mautic_user_index',
178
                        '%url%'       => $this->generateUrl('mautic_user_action', [
179
                            'objectAction' => 'edit',
180
                            'objectId'     => $user->getId(),
181
                        ]),
182
                    ]);
183
                }
184
            }
185
186
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
187
                return $this->postActionRedirect([
188
                    'returnUrl'       => $returnUrl,
189
                    'viewParameters'  => ['page' => $page],
190
                    'contentTemplate' => 'MauticUserBundle:User:index',
191
                    'passthroughVars' => [
192
                        'activeLink'    => '#mautic_user_index',
193
                        'mauticContent' => 'user',
194
                    ],
195
                ]);
196
            } elseif ($valid && !$cancelled) {
197
                return $this->editAction($user->getId(), true);
198
            }
199
        }
200
201
        return $this->delegateView([
202
            'viewParameters'  => ['form' => $form->createView()],
203
            'contentTemplate' => 'MauticUserBundle:User:form.html.php',
204
            'passthroughVars' => [
205
                'activeLink'    => '#mautic_user_new',
206
                'route'         => $action,
207
                'mauticContent' => 'user',
208
            ],
209
        ]);
210
    }
211
212
    /**
213
     * Generates edit form and processes post data.
214
     *
215
     * @param int  $objectId
216
     * @param bool $ignorePost
217
     *
218
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
219
     */
220
    public function editAction($objectId, $ignorePost = false)
221
    {
222
        if (!$this->get('mautic.security')->isGranted('user:users:edit')) {
223
            return $this->accessDenied();
224
        }
225
        $model = $this->getModel('user.user');
226
        $user  = $model->getEntity($objectId);
227
228
        //set the page we came from
229
        $page = $this->get('session')->get('mautic.user.page', 1);
230
231
        //set the return URL
232
        $returnUrl = $this->generateUrl('mautic_user_index', ['page' => $page]);
233
234
        $postActionVars = [
235
            'returnUrl'       => $returnUrl,
236
            'viewParameters'  => ['page' => $page],
237
            'contentTemplate' => 'MauticUserBundle:User:index',
238
            'passthroughVars' => [
239
                'activeLink'    => '#mautic_user_index',
240
                'mauticContent' => 'user',
241
            ],
242
        ];
243
244
        if (null === $user) {
245
            return $this->postActionRedirect(
246
                array_merge($postActionVars, [
247
                    'flashes' => [
248
                        [
249
                            'type'    => 'error',
250
                            'msg'     => 'mautic.user.user.error.notfound',
251
                            'msgVars' => ['%id%' => $objectId],
252
                        ],
253
                    ],
254
                ])
255
            );
256
        } elseif ($model->isLocked($user)) {
257
            //deny access if the entity is locked
258
            return $this->isLocked($postActionVars, $user, 'user.user');
259
        }
260
261
        $action = $this->generateUrl('mautic_user_action', ['objectAction' => 'edit', 'objectId' => $objectId]);
262
        $form   = $model->createForm($user, $this->get('form.factory'), $action);
263
264
        ///Check for a submitted form and process it
265
        if (!$ignorePost && 'POST' === $this->request->getMethod()) {
266
            $valid = false;
267
268
            if (!$cancelled = $this->isFormCancelled($form)) {
269
                //check to see if the password needs to be rehashed
270
                $formUser          = $this->request->request->get('user', []);
271
                $submittedPassword = $formUser['plainPassword']['password'] ?? null;
272
                $encoder           = $this->get('security.encoder_factory')->getEncoder($user);
273
                $password          = $model->checkNewPassword($user, $encoder, $submittedPassword);
274
275
                if ($valid = $this->isFormValid($form)) {
276
                    //form is valid so process the data
277
                    $user->setPassword($password);
278
                    $model->saveEntity($user, $form->get('buttons')->get('save')->isClicked());
279
280
                    //check if the user's locale has been downloaded already, fetch it if not
281
                    /** @var LanguageHelper $languageHelper */
282
                    $languageHelper     = $this->container->get('mautic.helper.language');
283
                    $installedLanguages = $languageHelper->getSupportedLanguages();
284
285
                    if ($user->getLocale() && !array_key_exists($user->getLocale(), $installedLanguages)) {
286
                        $fetchLanguage = $languageHelper->extractLanguagePackage($user->getLocale());
287
288
                        // If there is an error, we need to reset the user's locale to the default
289
                        if ($fetchLanguage['error']) {
290
                            $user->setLocale(null);
291
                            $model->saveEntity($user);
292
                            $message     = 'mautic.core.could.not.set.language';
293
                            $messageVars = [];
294
295
                            if (isset($fetchLanguage['message'])) {
296
                                $message = $fetchLanguage['message'];
297
                            }
298
299
                            if (isset($fetchLanguage['vars'])) {
300
                                $messageVars = $fetchLanguage['vars'];
301
                            }
302
303
                            $this->addFlash($message, $messageVars);
304
                        }
305
                    }
306
307
                    $this->addFlash('mautic.core.notice.updated', [
0 ignored issues
show
Deprecated Code introduced by
The function Mautic\CoreBundle\Contro...nController::addFlash() has been deprecated: Will be removed in Mautic 3.0. Use CommonController::flashBag->addFlash() instead. ( Ignorable by Annotation )

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

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

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

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

Loading history...
308
                        '%name%'      => $user->getName(),
309
                        '%menu_link%' => 'mautic_user_index',
310
                        '%url%'       => $this->generateUrl('mautic_user_action', [
311
                            'objectAction' => 'edit',
312
                            'objectId'     => $user->getId(),
313
                        ]),
314
                    ]);
315
                }
316
            } else {
317
                //unlock the entity
318
                $model->unlockEntity($user);
319
            }
320
321
            if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
322
                return $this->postActionRedirect($postActionVars);
323
            }
324
        } else {
325
            //lock the entity
326
            $model->lockEntity($user);
327
        }
328
329
        return $this->delegateView([
330
            'viewParameters'  => ['form' => $form->createView()],
331
            'contentTemplate' => 'MauticUserBundle:User:form.html.php',
332
            'passthroughVars' => [
333
                'activeLink'    => '#mautic_user_index',
334
                'route'         => $action,
335
                'mauticContent' => 'user',
336
            ],
337
        ]);
338
    }
339
340
    /**
341
     * Deletes a user object.
342
     *
343
     * @param int $objectId
344
     *
345
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
346
     */
347
    public function deleteAction($objectId)
348
    {
349
        if (!$this->get('mautic.security')->isGranted('user:users:delete')) {
350
            return $this->accessDenied();
351
        }
352
353
        $currentUser    = $this->user;
354
        $page           = $this->get('session')->get('mautic.user.page', 1);
355
        $returnUrl      = $this->generateUrl('mautic_user_index', ['page' => $page]);
356
        $success        = 0;
357
        $flashes        = [];
358
        $postActionVars = [
359
            'returnUrl'       => $returnUrl,
360
            'viewParameters'  => ['page' => $page],
361
            'contentTemplate' => 'MauticUserBundle:User:index',
362
            'passthroughVars' => [
363
                'activeLink'    => '#mautic_user_index',
364
                'route'         => $returnUrl,
365
                'success'       => $success,
366
                'mauticContent' => 'user',
367
            ],
368
        ];
369
        if ('POST' == $this->request->getMethod()) {
370
            //ensure the user logged in is not getting deleted
371
            if ((int) $currentUser->getId() !== (int) $objectId) {
372
                $model  = $this->getModel('user.user');
373
                $entity = $model->getEntity($objectId);
374
375
                if (null === $entity) {
376
                    $flashes[] = [
377
                        'type'    => 'error',
378
                        'msg'     => 'mautic.user.user.error.notfound',
379
                        'msgVars' => ['%id%' => $objectId],
380
                    ];
381
                } elseif ($model->isLocked($entity)) {
382
                    return $this->isLocked($postActionVars, $entity, 'user.user');
383
                } else {
384
                    $model->deleteEntity($entity);
385
                    $name      = $entity->getName();
386
                    $flashes[] = [
387
                        'type'    => 'notice',
388
                        'msg'     => 'mautic.core.notice.deleted',
389
                        'msgVars' => [
390
                            '%name%' => $name,
391
                            '%id%'   => $objectId,
392
                        ],
393
                    ];
394
                }
395
            } else {
396
                $flashes[] = [
397
                    'type' => 'error',
398
                    'msg'  => 'mautic.user.user.error.cannotdeleteself',
399
                ];
400
            }
401
        } //else don't do anything
402
403
        return $this->postActionRedirect(
404
            array_merge($postActionVars, [
405
                'flashes' => $flashes,
406
            ])
407
        );
408
    }
409
410
    /**
411
     * Contacts a user.
412
     *
413
     * @param int $objectId
414
     *
415
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
416
     */
417
    public function contactAction($objectId)
418
    {
419
        $model = $this->getModel('user.user');
420
        $user  = $model->getEntity($objectId);
421
422
        //user not found
423
        if (null === $user) {
424
            return $this->postActionRedirect([
425
                'returnUrl'       => $this->generateUrl('mautic_dashboard_index'),
426
                'contentTemplate' => 'MauticUserBundle:User:contact',
427
                'flashes'         => [
428
                    [
429
                        'type'    => 'error',
430
                        'msg'     => 'mautic.user.user.error.notfound',
431
                        'msgVars' => ['%id%' => $objectId],
432
                    ],
433
                ],
434
            ]);
435
        }
436
437
        $action = $this->generateUrl('mautic_user_action', ['objectAction' => 'contact', 'objectId' => $objectId]);
438
        $form   = $this->createForm(ContactType::class, [], ['action' => $action]);
439
440
        $currentUser = $this->user;
441
442
        if ('POST' == $this->request->getMethod()) {
443
            $contact   = $this->request->request->get('contact', []);
444
            $formUrl   = $contact['returnUrl'] ?? '';
445
            $returnUrl = $formUrl ? urldecode($formUrl) : $this->generateUrl('mautic_dashboard_index');
446
            $valid     = false;
447
448
            if (!$cancelled = $this->isFormCancelled($form)) {
449
                if ($valid = $this->isFormValid($form)) {
450
                    $subject = InputHelper::clean($form->get('msg_subject')->getData());
451
                    $body    = InputHelper::clean($form->get('msg_body')->getData());
452
                    $message = (new \Swift_Message())
453
                        ->setSubject($subject)
454
                        ->setFrom($currentUser->getEmail(), $currentUser->getName())
455
                        ->setTo($user->getEmail(), $user->getName())
456
                        ->setBody($body);
457
                    $this->get('mailer')->send($message);
458
459
                    $reEntity = $form->get('entity')->getData();
460
                    if (empty($reEntity)) {
461
                        $bundle   = $object   = 'user';
462
                        $entityId = $user->getId();
463
                    } else {
464
                        $bundle = $object = $reEntity;
465
                        if (strpos($reEntity, ':')) {
466
                            [$bundle, $object] = explode(':', $reEntity);
467
                        }
468
                        $entityId = $form->get('id')->getData();
469
                    }
470
471
                    $serializer = $this->get('jms_serializer');
472
                    $details    = $serializer->serialize([
473
                        'from'    => $currentUser->getName(),
474
                        'to'      => $user->getName(),
475
                        'subject' => $subject,
476
                        'message' => $body,
477
                    ], 'json');
478
479
                    $log = [
480
                        'bundle'    => $bundle,
481
                        'object'    => $object,
482
                        'objectId'  => $entityId,
483
                        'action'    => 'communication',
484
                        'details'   => $details,
485
                        'ipAddress' => $this->factory->getIpAddressFromRequest(),
486
                    ];
487
                    $this->getModel('core.auditlog')->writeToLog($log);
488
489
                    $this->addFlash('mautic.user.user.notice.messagesent', ['%name%' => $user->getName()]);
490
                }
491
            }
492
            if ($cancelled || $valid) {
493
                return $this->redirect($returnUrl);
494
            }
495
        } else {
496
            $reEntityId = (int) $this->request->get('id');
497
            $reSubject  = InputHelper::clean($this->request->get('subject'));
498
            $returnUrl  = InputHelper::clean($this->request->get('returnUrl', $this->generateUrl('mautic_dashboard_index')));
499
            $reEntity   = InputHelper::clean($this->request->get('entity'));
500
501
            $form->get('entity')->setData($reEntity);
502
            $form->get('id')->setData($reEntityId);
503
            $form->get('returnUrl')->setData($returnUrl);
504
505
            if (!empty($reEntity) && !empty($reEntityId)) {
506
                $model  = $this->getModel($reEntity);
507
                $entity = $model->getEntity($reEntityId);
508
509
                if (null !== $entity) {
510
                    $subject = $model->getUserContactSubject($reSubject, $entity);
511
                    $form->get('msg_subject')->setData($subject);
512
                }
513
            }
514
        }
515
516
        return $this->delegateView([
517
            'viewParameters' => [
518
                'form' => $form->createView(),
519
                'user' => $user,
520
            ],
521
            'contentTemplate' => 'MauticUserBundle:User:contact.html.php',
522
            'passthroughVars' => [
523
                'route'         => $action,
524
                'mauticContent' => 'user',
525
            ],
526
        ]);
527
    }
528
529
    /**
530
     * Deletes a group of entities.
531
     *
532
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
533
     */
534
    public function batchDeleteAction()
535
    {
536
        $page      = $this->get('session')->get('mautic.user.page', 1);
537
        $returnUrl = $this->generateUrl('mautic_user_index', ['page' => $page]);
538
        $flashes   = [];
539
540
        $postActionVars = [
541
            'returnUrl'       => $returnUrl,
542
            'viewParameters'  => ['page' => $page],
543
            'contentTemplate' => 'MauticUserBundle:User:index',
544
            'passthroughVars' => [
545
                'activeLink'    => '#mautic_user_index',
546
                'mauticContent' => 'user',
547
            ],
548
        ];
549
550
        if ('POST' == $this->request->getMethod()) {
551
            $model       = $this->getModel('user');
552
            $ids         = json_decode($this->request->query->get('ids', ''));
553
            $deleteIds   = [];
554
            $currentUser = $this->user;
555
556
            // Loop over the IDs to perform access checks pre-delete
557
            foreach ($ids as $objectId) {
558
                $entity = $model->getEntity($objectId);
559
560
                if ((int) $currentUser->getId() === (int) $objectId) {
561
                    $flashes[] = [
562
                        'type' => 'error',
563
                        'msg'  => 'mautic.user.user.error.cannotdeleteself',
564
                    ];
565
                } elseif (null === $entity) {
566
                    $flashes[] = [
567
                        'type'    => 'error',
568
                        'msg'     => 'mautic.user.user.error.notfound',
569
                        'msgVars' => ['%id%' => $objectId],
570
                    ];
571
                } elseif (!$this->get('mautic.security')->isGranted('user:users:delete')) {
572
                    $flashes[] = $this->accessDenied(true);
573
                } elseif ($model->isLocked($entity)) {
574
                    $flashes[] = $this->isLocked($postActionVars, $entity, 'user', true);
575
                } else {
576
                    $deleteIds[] = $objectId;
577
                }
578
            }
579
580
            // Delete everything we are able to
581
            if (!empty($deleteIds)) {
582
                $entities = $model->deleteEntities($deleteIds);
583
584
                $flashes[] = [
585
                    'type'    => 'notice',
586
                    'msg'     => 'mautic.user.user.notice.batch_deleted',
587
                    'msgVars' => [
588
                        '%count%' => count($entities),
589
                    ],
590
                ];
591
            }
592
        } //else don't do anything
593
594
        return $this->postActionRedirect(
595
            array_merge($postActionVars, [
596
                'flashes' => $flashes,
597
            ])
598
        );
599
    }
600
}
601