Completed
Push — master ( 4b4e40...af8835 )
by Craig
10:40 queued 04:02
created

UserAdministrationController::modifyAction()   B

Complexity

Conditions 10
Paths 8

Size

Total Lines 67
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 41
nc 8
nop 8
dl 0
loc 67
rs 7.6666
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula Foundation - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\ZAuthModule\Controller;
15
16
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
17
use Symfony\Component\HttpFoundation\RedirectResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Routing\Annotation\Route;
21
use Symfony\Component\Routing\RouterInterface;
22
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
23
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
24
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
25
use Translation\Extractor\Annotation\Desc;
26
use Zikula\Bundle\CoreBundle\Controller\AbstractController;
27
use Zikula\Bundle\CoreBundle\Event\GenericEvent;
28
use Zikula\Bundle\CoreBundle\Response\PlainResponse;
29
use Zikula\Bundle\HookBundle\Dispatcher\HookDispatcherInterface;
30
use Zikula\Bundle\HookBundle\Hook\ProcessHook;
31
use Zikula\Bundle\HookBundle\Hook\ValidationHook;
32
use Zikula\Bundle\HookBundle\Hook\ValidationProviders;
33
use Zikula\Component\SortableColumns\Column;
34
use Zikula\Component\SortableColumns\SortableColumns;
35
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
36
use Zikula\GroupsModule\Entity\GroupEntity;
37
use Zikula\ThemeModule\Engine\Annotation\Theme;
38
use Zikula\UsersModule\Api\ApiInterface\CurrentUserApiInterface;
39
use Zikula\UsersModule\Collector\AuthenticationMethodCollector;
40
use Zikula\UsersModule\Constant as UsersConstant;
41
use Zikula\UsersModule\Entity\RepositoryInterface\UserRepositoryInterface;
42
use Zikula\UsersModule\Entity\UserEntity;
43
use Zikula\UsersModule\Event\UserFormAwareEvent;
44
use Zikula\UsersModule\Event\UserFormDataEvent;
45
use Zikula\UsersModule\Helper\MailHelper as UsersMailHelper;
46
use Zikula\UsersModule\Helper\RegistrationHelper;
47
use Zikula\UsersModule\HookSubscriber\UserManagementUiHooksSubscriber;
48
use Zikula\UsersModule\RegistrationEvents;
49
use Zikula\UsersModule\UserEvents;
50
use Zikula\ZAuthModule\Entity\AuthenticationMappingEntity;
51
use Zikula\ZAuthModule\Entity\RepositoryInterface\AuthenticationMappingRepositoryInterface;
52
use Zikula\ZAuthModule\Form\Type\AdminCreatedUserType;
53
use Zikula\ZAuthModule\Form\Type\AdminModifyUserType;
54
use Zikula\ZAuthModule\Form\Type\BatchForcePasswordChangeType;
55
use Zikula\ZAuthModule\Form\Type\SendVerificationConfirmationType;
56
use Zikula\ZAuthModule\Form\Type\TogglePasswordConfirmationType;
57
use Zikula\ZAuthModule\Helper\AdministrationActionsHelper;
58
use Zikula\ZAuthModule\Helper\LostPasswordVerificationHelper;
59
use Zikula\ZAuthModule\Helper\MailHelper;
60
use Zikula\ZAuthModule\Helper\RegistrationVerificationHelper;
61
use Zikula\ZAuthModule\ZAuthConstant;
62
63
/**
64
 * Class UserAdministrationController
65
 * @Route("/admin")
66
 */
67
class UserAdministrationController extends AbstractController
68
{
69
    /**
70
     * @Route("/list/{sort}/{sortdir}/{letter}/{startnum}")
71
     * @Theme("admin")
72
     * @Template("@ZikulaZAuthModule/UserAdministration/list.html.twig")
73
     *
74
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the module
75
     */
76
    public function listAction(
77
        Request $request,
78
        AuthenticationMappingRepositoryInterface $authenticationMappingRepository,
79
        RouterInterface $router,
80
        AdministrationActionsHelper $actionsHelper,
81
        string $sort = 'uid',
82
        string $sortdir = 'DESC',
83
        string $letter = 'all',
84
        int $startnum = 0
85
    ): array {
86
        if (!$this->hasPermission('ZikulaZAuthModule', '::', ACCESS_MODERATE)) {
87
            throw new AccessDeniedException();
88
        }
89
        $startnum = $startnum > 0 ? $startnum - 1 : 0;
90
91
        $sortableColumns = new SortableColumns($router, 'zikulazauthmodule_useradministration_list', 'sort', 'sortdir');
92
        $sortableColumns->addColumns([new Column('uname'), new Column('uid')]);
93
        $sortableColumns->setOrderByFromRequest($request);
94
        $sortableColumns->setAdditionalUrlParameters([
95
            'letter' => $letter,
96
            'startnum' => $startnum
97
        ]);
98
99
        $filter = [];
100
        if (!empty($letter) && 'all' !== $letter) {
101
            $filter['uname'] = ['operator' => 'like', 'operand' => "${letter}%"];
102
        }
103
        $limit = 25;
104
105
        $mappings = $authenticationMappingRepository->query($filter, [$sort => $sortdir], $limit, $startnum);
106
107
        return [
108
            'sort' => $sortableColumns->generateSortableColumns(),
109
            'pager' => [
110
                'count' => $mappings->count(),
111
                'limit' => $limit
112
            ],
113
            'actionsHelper' => $actionsHelper,
114
            'mappings' => $mappings
115
        ];
116
    }
117
118
    /**
119
     * Called from UsersModule/Resources/public/js/Zikula.Users.Admin.View.js
120
     * to populate a username search
121
     *
122
     * @Route("/getusersbyfragmentastable", methods = {"POST"}, options={"expose"=true})
123
     */
124
    public function getUsersByFragmentAsTableAction(
125
        Request $request,
126
        AuthenticationMappingRepositoryInterface $authenticationMappingRepository,
127
        AdministrationActionsHelper $actionsHelper
128
    ): Response {
129
        if (!$this->hasPermission('ZikulaZAuthModule', '::', ACCESS_MODERATE)) {
130
            return new PlainResponse('');
131
        }
132
        $fragment = $request->request->get('fragment');
133
        $filter = [
134
            'uname' => ['operator' => 'like', 'operand' => $fragment . '%']
135
        ];
136
        $mappings = $authenticationMappingRepository->query($filter);
137
138
        return $this->render('@ZikulaZAuthModule/UserAdministration/userlist.html.twig', [
139
            'mappings' => $mappings,
140
            'actionsHelper' => $actionsHelper
141
        ], new PlainResponse());
142
    }
143
144
    /**
145
     * @Route("/user/create")
146
     * @Theme("admin")
147
     * @Template("@ZikulaZAuthModule/UserAdministration/create.html.twig")
148
     *
149
     * @return array|RedirectResponse
150
     * @throws AccessDeniedException Thrown if the user hasn't admin permissions for the module
151
     */
152
    public function createAction(
153
        Request $request,
154
        VariableApiInterface $variableApi,
155
        AuthenticationMethodCollector $authenticationMethodCollector,
156
        UserRepositoryInterface $userRepository,
157
        RegistrationHelper $registrationHelper,
158
        UsersMailHelper $mailHelper,
159
        EventDispatcherInterface $eventDispatcher,
160
        HookDispatcherInterface $hookDispatcher
161
    ) {
162
        if (!$this->hasPermission('ZikulaZAuthModule', '::', ACCESS_ADMIN)) {
163
            throw new AccessDeniedException();
164
        }
165
166
        $mapping = new AuthenticationMappingEntity();
167
        $form = $this->createForm(AdminCreatedUserType::class, $mapping, [
168
            'minimumPasswordLength' => $variableApi->get('ZikulaZAuthModule', ZAuthConstant::MODVAR_PASSWORD_MINIMUM_LENGTH, ZAuthConstant::PASSWORD_MINIMUM_LENGTH)
169
        ]);
170
        $formEvent = new UserFormAwareEvent($form);
171
        $eventDispatcher->dispatch($formEvent, UserEvents::EDIT_FORM);
172
        $form->handleRequest($request);
173
174
        $hook = new ValidationHook(new ValidationProviders());
175
        $hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_VALIDATE, $hook);
176
        $validators = $hook->getValidators();
177
178
        if ($form->isSubmitted() && $form->isValid() && !$validators->hasErrors()) {
179
            if ($form->get('submit')->isClicked()) {
0 ignored issues
show
Bug introduced by
The method isClicked() does not exist on Symfony\Component\Form\FormInterface. It seems like you code against a sub-type of Symfony\Component\Form\FormInterface such as Symfony\Component\Form\SubmitButton. ( Ignorable by Annotation )

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

179
            if ($form->get('submit')->/** @scrutinizer ignore-call */ isClicked()) {
Loading history...
180
                $mapping = $form->getData();
181
                $passToSend = $form['sendpass']->getData() ? $mapping->getPass() : '';
182
                $authMethodName = (ZAuthConstant::AUTHENTICATION_METHOD_EITHER === $mapping->getMethod()) ? ZAuthConstant::AUTHENTICATION_METHOD_UNAME : $mapping->getMethod();
183
                $authMethod = $authenticationMethodCollector->get($authMethodName);
184
185
                if ($request->hasSession() && ($session = $request->getSession())) {
186
                    $session->set(ZAuthConstant::MODVAR_EMAIL_VERIFICATION_REQUIRED, ($form['usermustverify']->getData() ? 'Y' : 'N'));
187
                }
188
189
                $userData = $mapping->getUserEntityData();
190
                if (null === $userData['uid']) {
191
                    unset($userData['uid']);
192
                }
193
                $user = new UserEntity();
194
                $user->merge($userData);
195
                $user->setAttribute(UsersConstant::AUTHENTICATION_METHOD_ATTRIBUTE_KEY, $mapping->getMethod());
196
                $registrationHelper->registerNewUser($user);
197
                if (UsersConstant::ACTIVATED_PENDING_REG === $user->getActivated()) {
198
                    $notificationErrors = $mailHelper->createAndSendRegistrationMail($user, $form['usernotification']->getData(), $form['adminnotification']->getData(), $passToSend);
199
                } else {
200
                    $notificationErrors = $mailHelper->createAndSendUserMail($user, $form['usernotification']->getData(), $form['adminnotification']->getData(), $passToSend);
201
                }
202
                if (!empty($notificationErrors)) {
203
                    $this->addFlash('error', 'Errors creating user!');
204
                    $this->addFlash('error', implode('<br />', $notificationErrors));
205
                }
206
                $userId = $user->getUid();
207
                $mapping->setUid($user->getUid());
208
                $mapping->setVerifiedEmail(!$form['usermustverify']->getData());
209
                if (!$authMethod->register($mapping->toArray())) {
210
                    $this->addFlash('error', 'The create process failed for an unknown reason.');
211
                    $userRepository->removeAndFlush($user);
212
                    $eventDispatcher->dispatch(new GenericEvent($userId), RegistrationEvents::DELETE_REGISTRATION);
213
214
                    return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
215
                }
216
                $formDataEvent = new UserFormDataEvent($user, $form);
217
                $eventDispatcher->dispatch($formDataEvent, UserEvents::EDIT_FORM_HANDLE);
218
                $hook = new ProcessHook($userId);
219
                $hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_PROCESS, $hook);
220
                $eventDispatcher->dispatch(new GenericEvent($user), RegistrationEvents::REGISTRATION_SUCCEEDED);
221
222
                if (UsersConstant::ACTIVATED_PENDING_REG === $user->getActivated()) {
223
                    $this->addFlash('status', 'Done! Created new registration application.');
224
                } elseif (null !== $user->getActivated()) {
0 ignored issues
show
introduced by
The condition null !== $user->getActivated() is always true.
Loading history...
225
                    $this->addFlash('status', 'Done! Created new user account.');
226
                } else {
227
                    $this->addFlash('error', 'Warning! New user information has been saved, however there may have been an issue saving it properly.');
228
                }
229
230
                return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
231
            }
232
            if ($form->get('cancel')->isClicked()) {
233
                $this->addFlash('status', 'Operation cancelled.');
234
            }
235
        }
236
237
        return [
238
            'form' => $form->createView(),
239
            'additional_templates' => isset($formEvent) ? $formEvent->getTemplates() : []
240
        ];
241
    }
242
243
    /**
244
     * @Route("/user/modify/{mapping}", requirements={"mapping" = "^[1-9]\d*$"})
245
     * @Theme("admin")
246
     * @Template("@ZikulaZAuthModule/UserAdministration/modify.html.twig")
247
     *
248
     * @return array|RedirectResponse
249
     * @throws AccessDeniedException Thrown if the user hasn't edit permissions for the mapping record
250
     */
251
    public function modifyAction(
252
        Request $request,
253
        AuthenticationMappingEntity $mapping,
254
        VariableApiInterface $variableApi,
255
        EncoderFactoryInterface $encoderFactory,
256
        UserRepositoryInterface $userRepository,
257
        AuthenticationMappingRepositoryInterface $authenticationMappingRepository,
258
        EventDispatcherInterface $eventDispatcher,
259
        HookDispatcherInterface $hookDispatcher
260
    ) {
261
        if (!$this->hasPermission('ZikulaZAuthModule::', $mapping->getUname() . '::' . $mapping->getUid(), ACCESS_EDIT)) {
262
            throw new AccessDeniedException();
263
        }
264
        if (1 === $mapping->getUid()) {
265
            throw new AccessDeniedException($this->trans("Error! You can't edit the guest account."));
266
        }
267
268
        $form = $this->createForm(AdminModifyUserType::class, $mapping, [
269
            'minimumPasswordLength' => $variableApi->get('ZikulaZAuthModule', ZAuthConstant::MODVAR_PASSWORD_MINIMUM_LENGTH, ZAuthConstant::PASSWORD_MINIMUM_LENGTH)
270
        ]);
271
        $originalMapping = clone $mapping;
272
        $formEvent = new UserFormAwareEvent($form);
273
        $eventDispatcher->dispatch($formEvent, UserEvents::EDIT_FORM);
274
        $form->handleRequest($request);
275
276
        $hook = new ValidationHook(new ValidationProviders());
277
        $hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_VALIDATE, $hook);
278
        $validators = $hook->getValidators();
279
280
        if ($form->isSubmitted() && $form->isValid() && !$validators->hasErrors()) {
281
            if ($form->get('submit')->isClicked()) {
282
                /** @var AuthenticationMappingEntity $mapping */
283
                $mapping = $form->getData();
284
                if ($form->get('setpass')->getData()) {
285
                    $mapping->setPass($encoderFactory->getEncoder($mapping)->encodePassword($mapping->getPass(), null));
286
                } else {
287
                    $mapping->setPass($originalMapping->getPass());
288
                }
289
                $authenticationMappingRepository->persistAndFlush($mapping);
290
                /** @var UserEntity $user */
291
                $user = $userRepository->find($mapping->getUid());
292
                $user->merge($mapping->getUserEntityData());
293
                $userRepository->persistAndFlush($user);
294
                $eventArgs = [
295
                    'action'    => 'setVar',
296
                    'field'     => 'uname',
297
                    'attribute' => null,
298
                ];
299
                $eventData = ['old_value' => $originalMapping->getUname()];
300
                $updateEvent = new GenericEvent($user, $eventArgs, $eventData);
301
                $eventDispatcher->dispatch($updateEvent, UserEvents::UPDATE_ACCOUNT);
302
303
                $formDataEvent = new UserFormDataEvent($user, $form);
304
                $eventDispatcher->dispatch($formDataEvent, UserEvents::EDIT_FORM_HANDLE);
305
                $hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_PROCESS, new ProcessHook($mapping->getUid()));
306
307
                $this->addFlash('status', "Done! Saved user's account information.");
308
            } elseif ($form->get('cancel')->isClicked()) {
309
                $this->addFlash('status', 'Operation cancelled.');
310
            }
311
312
            return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
313
        }
314
315
        return [
316
            'form' => $form->createView(),
317
            'additional_templates' => isset($formEvent) ? $formEvent->getTemplates() : []
318
        ];
319
    }
320
321
    /**
322
     * @Route("/verify/{mapping}", requirements={"mapping" = "^[1-9]\d*$"})
323
     * @Theme("admin")
324
     * @Template("@ZikulaZAuthModule/UserAdministration/verify.html.twig")
325
     *
326
     * @return array|RedirectResponse
327
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the module
328
     */
329
    public function verifyAction(
330
        Request $request,
331
        AuthenticationMappingEntity $mapping,
332
        AuthenticationMappingRepositoryInterface $authenticationMappingRepository,
333
        RegistrationVerificationHelper $registrationVerificationHelper
334
    ) {
335
        if (!$this->hasPermission('ZikulaZAuthModule', '::', ACCESS_MODERATE)) {
336
            throw new AccessDeniedException();
337
        }
338
        $form = $this->createForm(SendVerificationConfirmationType::class, [
339
            'mapping' => $mapping->getId()
340
        ]);
341
342
        $form->handleRequest($request);
343
        if ($form->isSubmitted() && $form->isValid()) {
344
            if ($form->get('confirm')->isClicked()) {
345
                /** @var AuthenticationMappingEntity $modifiedMapping */
346
                $modifiedMapping = $authenticationMappingRepository->find($form->get('mapping')->getData());
347
                $verificationSent = $registrationVerificationHelper->sendVerificationCode($modifiedMapping);
348
                if (!$verificationSent) {
349
                    $this->addFlash('error', $this->trans('Sorry! There was a problem sending a verification code to %sub%.', ['%sub%' => $modifiedMapping->getUname()]));
350
                } else {
351
                    $this->addFlash('status', $this->trans('Done! Verification code sent to %sub%.', ['%sub%' => $modifiedMapping->getUname()]));
352
                }
353
            }
354
            if ($form->get('cancel')->isClicked()) {
355
                $this->addFlash('status', 'Operation cancelled.');
356
            }
357
358
            return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
359
        }
360
361
        return [
362
            'form' => $form->createView(),
363
            'mapping' => $mapping
364
        ];
365
    }
366
367
    /**
368
     * @Route("/send-confirmation/{mapping}", requirements={"mapping" = "^[1-9]\d*$"})
369
     *
370
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the mapping record
371
     */
372
    public function sendConfirmationAction(
373
        AuthenticationMappingEntity $mapping,
374
        LostPasswordVerificationHelper $lostPasswordVerificationHelper,
375
        MailHelper $mailHelper
376
    ): RedirectResponse {
377
        if (!$this->hasPermission('ZikulaZAuthModule', $mapping->getUname() . '::' . $mapping->getUid(), ACCESS_MODERATE)) {
378
            throw new AccessDeniedException();
379
        }
380
        $changePasswordExpireDays = $this->getVar(ZAuthConstant::MODVAR_EXPIRE_DAYS_CHANGE_PASSWORD, ZAuthConstant::DEFAULT_EXPIRE_DAYS_CHANGE_PASSWORD);
381
        $lostPasswordId = $lostPasswordVerificationHelper->createLostPasswordId($mapping);
382
        $mailSent = $mailHelper->sendNotification($mapping->getEmail(), 'lostpassword', [
383
            'uname' => $mapping->getUname(),
384
            'validDays' => $changePasswordExpireDays,
385
            'lostPasswordId' => $lostPasswordId,
386
            'requestedByAdmin' => true
387
        ]);
388
        if ($mailSent) {
389
            $this->addFlash('status', $this->trans('Done! The password recovery verification link for %userName% has been sent via e-mail.', ['%userName%' => $mapping->getUname()]));
390
        }
391
392
        return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
393
    }
394
395
    /**
396
     * @Route("/send-username/{mapping}", requirements={"mapping" = "^[1-9]\d*$"})
397
     *
398
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the mapping record
399
     */
400
    public function sendUserNameAction(
401
        AuthenticationMappingEntity $mapping,
402
        MailHelper $mailHelper
403
    ): RedirectResponse {
404
        if (!$this->hasPermission('ZikulaZAuthModule', $mapping->getUname() . '::' . $mapping->getUid(), ACCESS_MODERATE)) {
405
            throw new AccessDeniedException();
406
        }
407
        $mailSent = $mailHelper->sendNotification($mapping->getEmail(), 'lostuname', [
408
            'uname' => $mapping->getUname(),
409
            'requestedByAdmin' => true,
410
        ]);
411
412
        if ($mailSent) {
413
            $this->addFlash('status', $this->trans('Done! The user name for %userName% has been sent via e-mail.', ['%userName%' => $mapping->getUname()]));
414
        }
415
416
        return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
417
    }
418
419
    /**
420
     * @Route("/toggle-password-change/{user}", requirements={"user" = "^[1-9]\d*$"})
421
     * @Theme("admin")
422
     * @Template("@ZikulaZAuthModule/UserAdministration/togglePasswordChange.html.twig")
423
     *
424
     * @param Request $request
425
     * @param UserEntity $user // note: this is intentionally left as UserEntity instead of mapping because of need to access attributes
426
     *
427
     * @return array|RedirectResponse
428
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the user record
429
     */
430
    public function togglePasswordChangeAction(Request $request, UserEntity $user)
431
    {
432
        if (!$this->hasPermission('ZikulaZAuthModule', $user->getUname() . '::' . $user->getUid(), ACCESS_MODERATE)) {
433
            throw new AccessDeniedException();
434
        }
435
        if ($user->getAttributes()->containsKey(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY)) {
436
            $mustChangePass = $user->getAttributes()->get(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY);
437
        } else {
438
            $mustChangePass = false;
439
        }
440
        $form = $this->createForm(TogglePasswordConfirmationType::class, [
441
            'uid' => $user->getUid()
442
        ], [
443
            'mustChangePass' => $mustChangePass
444
        ]);
445
        $form->handleRequest($request);
446
        if ($form->isSubmitted() && $form->isValid()) {
447
            if ($form->get('toggle')->isClicked()) {
448
                if ($user->getAttributes()->containsKey(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY) && (bool)$user->getAttributes()->get(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY)) {
449
                    $user->getAttributes()->remove(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY);
450
                    $this->addFlash('success', $this->trans('Done! A password change will no longer be required for %userName%.', ['%userName%' => $user->getUname()]));
451
                } else {
452
                    $user->setAttribute(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY, true);
453
                    $this->addFlash('success', $this->trans('Done! A password change will be required the next time %userName% logs in.', ['%userName%' => $user->getUname()]));
454
                }
455
                $this->getDoctrine()->getManager()->flush();
456
            } elseif ($form->get('cancel')->isClicked()) {
457
                $this->addFlash('info', 'Operation cancelled.');
458
            }
459
460
            return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
461
        }
462
463
        return [
464
            'form' => $form->createView(),
465
            'mustChangePass' => $mustChangePass,
466
            'user' => $user
467
        ];
468
    }
469
470
    /**
471
     * @Route("/batch-force-password-change")
472
     * @Theme("admin")
473
     * @Template("@ZikulaZAuthModule/UserAdministration/batchForcePasswordChange.html.twig")
474
     *
475
     * @return array|RedirectResponse
476
     * @throws AccessDeniedException Thrown if the user hasn't moderate permissions for the user record
477
     */
478
    public function batchForcePasswordChangeAction(
479
        CurrentUserApiInterface $currentUserApi,
480
        Request $request
481
    ) {
482
        if (!$this->hasPermission('ZikulaZAuthModule', '::', ACCESS_ADMIN)) {
483
            throw new AccessDeniedException();
484
        }
485
        $form = $this->createForm(BatchForcePasswordChangeType::class);
486
        $form->handleRequest($request);
487
        if ($form->isSubmitted() && $form->isValid()) {
488
            if ($form->get('submit')->isClicked()) {
489
                $users = $this->getUsers($form->get('group')->getData(), $currentUserApi->get('uid'));
490
                $count = 0;
491
                foreach ($users as $user) {
492
                    $user->setAttribute(ZAuthConstant::REQUIRE_PASSWORD_CHANGE_KEY, true);
493
                    $count++;
494
                    if ($count % 20 === 0) {
495
                        $this->getDoctrine()->getManager()->flush(); // flush manager every 20 reps
496
                    }
497
                }
498
                $this->getDoctrine()->getManager()->flush(); // flush remaining
499
                /** @Desc("{count, plural,\n  one   {# user was processed!}\n  other {# users were processed!}\n}") */
500
                $this->addFlash('info', $this->trans('plural_n.users.processed.', ['%count%' => $count]));
501
            } elseif ($form->get('cancel')->isClicked()) {
502
                $this->addFlash('info', 'Operation cancelled.');
503
            }
504
505
            return $this->redirectToRoute('zikulazauthmodule_useradministration_list');
506
        }
507
508
        return [
509
            'form' => $form->createView(),
510
        ];
511
    }
512
513
    private function getUsers($selector, int $currentUser)
514
    {
515
        if (!in_array($selector, ['all', 'old']) && !is_int($selector)) {
516
            return [];
517
        }
518
        $authenticationMappingRepository = $this->getDoctrine()->getRepository(AuthenticationMappingEntity::class);
519
        $toUsersArray = function($mappings) {
520
            $uids = [];
521
            foreach ($mappings as $mapping) {
522
                $uids[] = $mapping->getUid();
523
            }
524
            $userRepository = $this->getDoctrine()->getRepository(UserEntity::class);
525
526
            return $userRepository->findByUids($uids);
527
        };
528
        switch ($selector) {
529
            case 'old':
530
                $mappings = $authenticationMappingRepository->getByExpiredPasswords();
531
                $users = $toUsersArray($mappings);
532
                break;
533
            case 'all':
534
                $mappings = $authenticationMappingRepository->findAll();
535
                $users = $toUsersArray($mappings);
536
                break;
537
            default: //group id
538
                $groupRepository = $this->getDoctrine()->getRepository(GroupEntity::class);
539
                $group = $groupRepository->find($selector);
540
                if ($group && $group instanceof GroupEntity) {
541
                    $users = $group->getUsers();
542
                    foreach ($users as $user) {
543
                        if (!$authenticationMappingRepository->getByZikulaId($user->getUid())) {
544
                            $users->removeElement($user);
545
                        }
546
                    }
547
                    $users = $users->toArray();
548
                }
549
        }
550
551
        if (is_array($users) && isset($users[$currentUser])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $users does not seem to be defined for all execution paths leading up to this point.
Loading history...
552
            unset($users[$currentUser]); // remove the current user (admin)
553
            unset($users[1]); // remove guest user if included
554
        }
555
556
        return $users;
557
    }
558
}
559