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\UsersModule\Controller; |
15
|
|
|
|
16
|
|
|
use Doctrine\Common\Collections\ArrayCollection; |
17
|
|
|
use InvalidArgumentException; |
18
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
19
|
|
|
use Symfony\Component\Form\FormInterface; |
20
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
21
|
|
|
use Symfony\Component\HttpFoundation\Request; |
22
|
|
|
use Symfony\Component\HttpFoundation\Response; |
23
|
|
|
use Symfony\Component\Routing\Annotation\Route; |
24
|
|
|
use Symfony\Component\Routing\RouterInterface; |
25
|
|
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException; |
26
|
|
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; |
27
|
|
|
use Translation\Extractor\Annotation\Desc; |
28
|
|
|
use Zikula\Bundle\CoreBundle\Controller\AbstractController; |
29
|
|
|
use Zikula\Bundle\CoreBundle\Event\GenericEvent; |
30
|
|
|
use Zikula\Bundle\CoreBundle\Response\PlainResponse; |
31
|
|
|
use Zikula\Bundle\HookBundle\Dispatcher\HookDispatcherInterface; |
32
|
|
|
use Zikula\Bundle\HookBundle\Hook\ProcessHook; |
33
|
|
|
use Zikula\Bundle\HookBundle\Hook\ValidationHook; |
34
|
|
|
use Zikula\Bundle\HookBundle\Hook\ValidationProviders; |
35
|
|
|
use Zikula\Component\SortableColumns\Column; |
36
|
|
|
use Zikula\Component\SortableColumns\SortableColumns; |
37
|
|
|
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface; |
38
|
|
|
use Zikula\GroupsModule\Constant; |
39
|
|
|
use Zikula\PermissionsModule\Annotation\PermissionCheck; |
40
|
|
|
use Zikula\ThemeModule\Engine\Annotation\Theme; |
41
|
|
|
use Zikula\UsersModule\Api\ApiInterface\CurrentUserApiInterface; |
42
|
|
|
use Zikula\UsersModule\Constant as UsersConstant; |
43
|
|
|
use Zikula\UsersModule\Entity\RepositoryInterface\UserRepositoryInterface; |
44
|
|
|
use Zikula\UsersModule\Entity\UserEntity; |
45
|
|
|
use Zikula\UsersModule\Event\UserFormAwareEvent; |
46
|
|
|
use Zikula\UsersModule\Event\UserFormDataEvent; |
47
|
|
|
use Zikula\UsersModule\Form\Type\AdminModifyUserType; |
48
|
|
|
use Zikula\UsersModule\Form\Type\DeleteConfirmationType; |
49
|
|
|
use Zikula\UsersModule\Form\Type\DeleteType; |
50
|
|
|
use Zikula\UsersModule\Form\Type\MailType; |
51
|
|
|
use Zikula\UsersModule\Form\Type\RegistrationType\ApproveRegistrationConfirmationType; |
52
|
|
|
use Zikula\UsersModule\Form\Type\SearchUserType; |
53
|
|
|
use Zikula\UsersModule\Helper\AdministrationActionsHelper; |
54
|
|
|
use Zikula\UsersModule\Helper\MailHelper; |
55
|
|
|
use Zikula\UsersModule\Helper\RegistrationHelper; |
56
|
|
|
use Zikula\UsersModule\HookSubscriber\UserManagementUiHooksSubscriber; |
57
|
|
|
use Zikula\UsersModule\RegistrationEvents; |
58
|
|
|
use Zikula\UsersModule\UserEvents; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Class UserAdministrationController |
62
|
|
|
* |
63
|
|
|
* @Route("/admin") |
64
|
|
|
*/ |
65
|
|
|
class UserAdministrationController extends AbstractController |
66
|
|
|
{ |
67
|
|
|
/** |
68
|
|
|
* @Route("/list/{sort}/{sortdir}/{letter}/{startnum}") |
69
|
|
|
* @PermissionCheck("moderate") |
70
|
|
|
* @Theme("admin") |
71
|
|
|
* @Template("@ZikulaUsersModule/UserAdministration/list.html.twig") |
72
|
|
|
*/ |
73
|
|
|
public function listAction( |
74
|
|
|
Request $request, |
75
|
|
|
UserRepositoryInterface $userRepository, |
76
|
|
|
RouterInterface $router, |
77
|
|
|
AdministrationActionsHelper $actionsHelper, |
78
|
|
|
string $sort = 'uid', |
79
|
|
|
string $sortdir = 'DESC', |
80
|
|
|
string $letter = 'all', |
81
|
|
|
int $startnum = 0 |
82
|
|
|
): array { |
83
|
|
|
$startnum = $startnum > 0 ? $startnum - 1 : 0; |
84
|
|
|
|
85
|
|
|
$sortableColumns = new SortableColumns($router, 'zikulausersmodule_useradministration_list', 'sort', 'sortdir'); |
86
|
|
|
$sortableColumns->addColumns([new Column('uname'), new Column('uid'), new Column('registrationDate'), new Column('lastLogin'), new Column('activated')]); |
87
|
|
|
$sortableColumns->setOrderByFromRequest($request); |
88
|
|
|
$sortableColumns->setAdditionalUrlParameters([ |
89
|
|
|
'letter' => $letter, |
90
|
|
|
'startnum' => $startnum |
91
|
|
|
]); |
92
|
|
|
|
93
|
|
|
$filter = []; |
94
|
|
|
if (!empty($letter) && 'all' !== $letter) { |
95
|
|
|
$filter['uname'] = ['operator' => 'like', 'operand' => "${letter}%"]; |
96
|
|
|
} |
97
|
|
|
$limit = $this->getVar(UsersConstant::MODVAR_ITEMS_PER_PAGE, UsersConstant::DEFAULT_ITEMS_PER_PAGE); |
98
|
|
|
$users = $userRepository->query($filter, [$sort => $sortdir], $limit, $startnum); |
99
|
|
|
|
100
|
|
|
return [ |
101
|
|
|
'sort' => $sortableColumns->generateSortableColumns(), |
102
|
|
|
'pager' => [ |
103
|
|
|
'count' => $users->count(), |
104
|
|
|
'limit' => $limit |
105
|
|
|
], |
106
|
|
|
'actionsHelper' => $actionsHelper, |
107
|
|
|
'users' => $users |
108
|
|
|
]; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Called from UsersModule/Resources/public/js/Zikula.Users.Admin.View.js |
113
|
|
|
* to populate a username search |
114
|
|
|
* |
115
|
|
|
* @Route("/getusersbyfragmentastable", methods = {"POST"}, options={"expose"=true}) |
116
|
|
|
*/ |
117
|
|
|
public function getUsersByFragmentAsTableAction( |
118
|
|
|
Request $request, |
119
|
|
|
UserRepositoryInterface $userRepository, |
120
|
|
|
AdministrationActionsHelper $actionsHelper |
121
|
|
|
): Response { |
122
|
|
|
if (!$this->hasPermission('ZikulaUsersModule', '::', ACCESS_MODERATE)) { |
123
|
|
|
return new PlainResponse(''); |
124
|
|
|
} |
125
|
|
|
$fragment = $request->request->get('fragment'); |
126
|
|
|
$filter = [ |
127
|
|
|
'activated' => ['operator' => 'notIn', 'operand' => [ |
128
|
|
|
UsersConstant::ACTIVATED_PENDING_REG, |
129
|
|
|
UsersConstant::ACTIVATED_PENDING_DELETE |
130
|
|
|
]], |
131
|
|
|
'uname' => ['operator' => 'like', 'operand' => "${fragment}%"] |
132
|
|
|
]; |
133
|
|
|
$users = $userRepository->query($filter); |
134
|
|
|
|
135
|
|
|
return $this->render('@ZikulaUsersModule/UserAdministration/userlist.html.twig', [ |
136
|
|
|
'users' => $users, |
137
|
|
|
'actionsHelper' => ${$actionsHelper} |
138
|
|
|
], new PlainResponse()); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @Route("/user/modify/{user}", requirements={"user" = "^[1-9]\d*$"}) |
143
|
|
|
* @Theme("admin") |
144
|
|
|
* @Template("@ZikulaUsersModule/UserAdministration/modify.html.twig") |
145
|
|
|
* |
146
|
|
|
* @return array|RedirectResponse |
147
|
|
|
* @throws AccessDeniedException Thrown if the user hasn't edit permissions for the user record |
148
|
|
|
*/ |
149
|
|
|
public function modifyAction( |
150
|
|
|
Request $request, |
151
|
|
|
UserEntity $user, |
152
|
|
|
CurrentUserApiInterface $currentUserApi, |
153
|
|
|
VariableApiInterface $variableApi, |
154
|
|
|
EventDispatcherInterface $eventDispatcher, |
155
|
|
|
HookDispatcherInterface $hookDispatcher |
156
|
|
|
) { |
157
|
|
|
if (!$this->hasPermission('ZikulaUsersModule::', $user->getUname() . '::' . $user->getUid(), ACCESS_EDIT)) { |
158
|
|
|
throw new AccessDeniedException(); |
159
|
|
|
} |
160
|
|
|
if (UsersConstant::USER_ID_ANONYMOUS === $user->getUid()) { |
161
|
|
|
throw new AccessDeniedException($this->trans("Error! You can't edit the guest account.")); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$form = $this->createForm(AdminModifyUserType::class, $user); |
165
|
|
|
$originalUserName = $user->getUname(); |
166
|
|
|
$originalGroups = $user->getGroups()->toArray(); |
167
|
|
|
$formEvent = new UserFormAwareEvent($form); |
168
|
|
|
$eventDispatcher->dispatch($formEvent, UserEvents::EDIT_FORM); |
169
|
|
|
$form->handleRequest($request); |
170
|
|
|
|
171
|
|
|
$hook = new ValidationHook(new ValidationProviders()); |
172
|
|
|
$hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_VALIDATE, $hook); |
173
|
|
|
$validators = $hook->getValidators(); |
174
|
|
|
|
175
|
|
|
if ($form->isSubmitted() && $form->isValid() && !$validators->hasErrors()) { |
176
|
|
|
if ($form->get('submit')->isClicked()) { |
|
|
|
|
177
|
|
|
$user = $form->getData(); |
178
|
|
|
$this->checkSelf($currentUserApi, $variableApi, $user, $originalGroups); |
179
|
|
|
|
180
|
|
|
$formDataEvent = new UserFormDataEvent($user, $form); |
181
|
|
|
$eventDispatcher->dispatch($formDataEvent, UserEvents::EDIT_FORM_HANDLE); |
182
|
|
|
|
183
|
|
|
$this->getDoctrine()->getManager()->flush(); |
184
|
|
|
|
185
|
|
|
$eventArgs = [ |
186
|
|
|
'action' => 'setVar', |
187
|
|
|
'field' => 'uname', |
188
|
|
|
'attribute' => null, |
189
|
|
|
]; |
190
|
|
|
$eventData = ['old_value' => $originalUserName]; |
191
|
|
|
$updateEvent = new GenericEvent($user, $eventArgs, $eventData); |
192
|
|
|
$eventDispatcher->dispatch($updateEvent, UserEvents::UPDATE_ACCOUNT); |
193
|
|
|
|
194
|
|
|
$hookDispatcher->dispatch(UserManagementUiHooksSubscriber::EDIT_PROCESS, new ProcessHook($user->getUid())); |
195
|
|
|
|
196
|
|
|
$this->addFlash('status', "Done! Saved user's account information."); |
197
|
|
|
} elseif ($form->get('cancel')->isClicked()) { |
198
|
|
|
$this->addFlash('status', 'Operation cancelled.'); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
return $this->redirectToRoute('zikulausersmodule_useradministration_list'); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
return [ |
205
|
|
|
'form' => $form->createView(), |
206
|
|
|
'additional_templates' => isset($formEvent) ? $formEvent->getTemplates() : [] |
207
|
|
|
]; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @Route("/approve/{user}/{force}", requirements={"user" = "^[1-9]\d*$"}) |
212
|
|
|
* @PermissionCheck("moderate") |
213
|
|
|
* @Theme("admin") |
214
|
|
|
* @Template("@ZikulaUsersModule/UserAdministration/approve.html.twig") |
215
|
|
|
* |
216
|
|
|
* @return array|RedirectResponse |
217
|
|
|
*/ |
218
|
|
|
public function approveAction( |
219
|
|
|
Request $request, |
220
|
|
|
UserEntity $user, |
221
|
|
|
RegistrationHelper $registrationHelper, |
222
|
|
|
MailHelper $mailHelper, |
223
|
|
|
bool $force = false |
224
|
|
|
) { |
225
|
|
|
$forceVerification = $this->hasPermission('ZikulaUsersModule', '::', ACCESS_ADMIN) && $force; |
226
|
|
|
$form = $this->createForm(ApproveRegistrationConfirmationType::class, [ |
227
|
|
|
'user' => $user->getUid(), |
228
|
|
|
'force' => $forceVerification |
229
|
|
|
], [ |
230
|
|
|
'buttonLabel' => $this->trans('Approve') |
231
|
|
|
]); |
232
|
|
|
$redirectToRoute = 'zikulausersmodule_useradministration_list'; |
233
|
|
|
|
234
|
|
|
if (!$forceVerification) { |
235
|
|
|
if ($user->isApproved()) { |
236
|
|
|
$this->addFlash('error', $this->trans('Warning! Nothing to do! %sub% is already approved.', ['%sub%' => $user->getUname()])); |
237
|
|
|
|
238
|
|
|
return $this->redirectToRoute($redirectToRoute); |
239
|
|
|
} |
240
|
|
|
if (!$user->isApproved() && !$this->hasPermission('ZikulaUsersModule::', '::', ACCESS_ADMIN)) { |
241
|
|
|
$this->addFlash('error', $this->trans('Error! %sub% cannot be approved.', ['%sub%' => $user->getUname()])); |
242
|
|
|
|
243
|
|
|
return $this->redirectToRoute($redirectToRoute); |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
$form->handleRequest($request); |
248
|
|
|
if ($form->isSubmitted() && $form->isValid()) { |
249
|
|
|
if ($form->get('confirm')->isClicked()) { |
250
|
|
|
$registrationHelper->approve($user); |
251
|
|
|
if (UsersConstant::ACTIVATED_PENDING_REG === $user->getActivated()) { |
252
|
|
|
$notificationErrors = $mailHelper->createAndSendRegistrationMail($user, true, false); |
253
|
|
|
} else { |
254
|
|
|
$notificationErrors = $mailHelper->createAndSendUserMail($user, true, false); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
if ($notificationErrors) { |
258
|
|
|
$this->addFlash('error', implode('<br />', $notificationErrors)); |
259
|
|
|
} |
260
|
|
|
$this->addFlash('status', $this->trans('Done! %sub% has been approved.', ['%sub%' => $user->getUname()])); |
261
|
|
|
} elseif ($form->get('cancel')->isClicked()) { |
262
|
|
|
$this->addFlash('status', 'Operation cancelled.'); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
return $this->redirectToRoute($redirectToRoute); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
return [ |
269
|
|
|
'form' => $form->createView(), |
270
|
|
|
'user' => $user |
271
|
|
|
]; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @Route("/delete/{user}", requirements={"user" = "^[1-9]\d*$"}) |
276
|
|
|
* @PermissionCheck("delete") |
277
|
|
|
* @Theme("admin") |
278
|
|
|
* @Template("@ZikulaUsersModule/UserAdministration/delete.html.twig") |
279
|
|
|
* |
280
|
|
|
* @return array|RedirectResponse |
281
|
|
|
*/ |
282
|
|
|
public function deleteAction( |
283
|
|
|
Request $request, |
284
|
|
|
CurrentUserApiInterface $currentUserApi, |
285
|
|
|
UserRepositoryInterface $userRepository, |
286
|
|
|
HookDispatcherInterface $hookDispatcher, |
287
|
|
|
EventDispatcherInterface $eventDispatcher, |
288
|
|
|
UserEntity $user = null |
289
|
|
|
) { |
290
|
|
|
$users = new ArrayCollection(); |
291
|
|
|
if ('POST' === $request->getMethod()) { |
292
|
|
|
$deleteForm = $this->createForm(DeleteType::class, [], [ |
293
|
|
|
'choices' => $userRepository->queryBySearchForm(), |
294
|
|
|
'action' => $this->generateUrl('zikulausersmodule_useradministration_delete') |
295
|
|
|
]); |
296
|
|
|
$deleteForm->handleRequest($request); |
297
|
|
|
if ($deleteForm->isSubmitted() && $deleteForm->isValid()) { |
298
|
|
|
$data = $deleteForm->getData(); |
299
|
|
|
$users = $data['users']; |
300
|
|
|
} |
301
|
|
|
} else { |
302
|
|
|
if (isset($user)) { |
303
|
|
|
$users->add($user); |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
$uids = []; |
307
|
|
|
foreach ($users as $affectedUser) { |
308
|
|
|
$uids[] = $affectedUser->getUid(); |
309
|
|
|
} |
310
|
|
|
$usersImploded = implode(',', $uids); |
311
|
|
|
|
312
|
|
|
$deleteConfirmationForm = $this->createForm(DeleteConfirmationType::class, [ |
313
|
|
|
'users' => $usersImploded |
314
|
|
|
]); |
315
|
|
|
$deleteConfirmationForm->handleRequest($request); |
316
|
|
|
if ($users instanceof ArrayCollection && $users->isEmpty() && !$deleteConfirmationForm->isSubmitted()) { |
317
|
|
|
throw new InvalidArgumentException($this->trans('No users selected.')); |
318
|
|
|
} |
319
|
|
|
if ($deleteConfirmationForm->isSubmitted()) { |
320
|
|
|
if ($deleteConfirmationForm->get('cancel')->isClicked()) { |
321
|
|
|
$this->addFlash('success', 'Operation cancelled.'); |
322
|
|
|
|
323
|
|
|
return $this->redirectToRoute('zikulausersmodule_useradministration_list'); |
324
|
|
|
} |
325
|
|
|
$userIdsImploded = $deleteConfirmationForm->get('users')->getData(); |
326
|
|
|
$userIds = explode(',', $userIdsImploded); |
327
|
|
|
$valid = true; |
328
|
|
|
foreach ($userIds as $k => $uid) { |
329
|
|
|
if (in_array($uid, [UsersConstant::USER_ID_ANONYMOUS, UsersConstant::USER_ID_ADMIN, $currentUserApi->get('uid')], true)) { |
330
|
|
|
unset($userIds[$k]); |
331
|
|
|
$this->addFlash('danger', $this->trans('You are not allowed to delete user id %uid%', ['%uid%' => $uid])); |
332
|
|
|
continue; |
333
|
|
|
} |
334
|
|
|
$event = new GenericEvent(null, ['id' => $uid], new ValidationProviders()); |
335
|
|
|
$validators = $eventDispatcher->dispatch($event, UserEvents::DELETE_VALIDATE)->getData(); |
336
|
|
|
$hook = new ValidationHook($validators); |
337
|
|
|
$hookDispatcher->dispatch(UserManagementUiHooksSubscriber::DELETE_VALIDATE, $hook); |
338
|
|
|
$validators = $hook->getValidators(); |
339
|
|
|
if ($validators->hasErrors()) { |
340
|
|
|
$valid = false; |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
if ($valid && $deleteConfirmationForm->isValid()) { |
344
|
|
|
// send email to 'denied' registrations. see MailHelper::sendNotification (regdeny) #2915 |
345
|
|
|
$deletedUsers = $userRepository->query(['uid' => ['operator' => 'in', 'operand' => $userIds]]); |
346
|
|
|
foreach ($deletedUsers as $deletedUser) { |
347
|
|
|
$eventName = UsersConstant::ACTIVATED_ACTIVE === $deletedUser->getActivated() ? UserEvents::DELETE_ACCOUNT : RegistrationEvents::DELETE_REGISTRATION; |
348
|
|
|
$eventDispatcher->dispatch(new GenericEvent($deletedUser->getUid()), $eventName); |
349
|
|
|
$eventDispatcher->dispatch(new GenericEvent(null, ['id' => $deletedUser->getUid()]), UserEvents::DELETE_PROCESS); |
350
|
|
|
$hookDispatcher->dispatch(UserManagementUiHooksSubscriber::DELETE_PROCESS, new ProcessHook($deletedUser->getUid())); |
351
|
|
|
$userRepository->removeAndFlush($deletedUser); |
352
|
|
|
} |
353
|
|
|
$this->addFlash( |
354
|
|
|
'success', |
355
|
|
|
/** @Desc("{count, plural,\n one {User deleted!}\n other {# users deleted!}\n}") */ |
356
|
|
|
$this->getTranslator()->trans( |
357
|
|
|
'plural_n.users.deleted', |
358
|
|
|
['%count%' => count($deletedUsers)] |
359
|
|
|
) |
360
|
|
|
); |
361
|
|
|
|
362
|
|
|
return $this->redirectToRoute('zikulausersmodule_useradministration_list'); |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
return [ |
367
|
|
|
'users' => $users, |
368
|
|
|
'form' => $deleteConfirmationForm->createView() |
369
|
|
|
]; |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* @Route("/search") |
374
|
|
|
* @PermissionCheck("moderate") |
375
|
|
|
* @Theme("admin") |
376
|
|
|
* @Template("@ZikulaUsersModule/UserAdministration/search.html.twig") |
377
|
|
|
* |
378
|
|
|
* @return array|Response |
379
|
|
|
*/ |
380
|
|
|
public function searchAction( |
381
|
|
|
Request $request, |
382
|
|
|
UserRepositoryInterface $userRepository, |
383
|
|
|
VariableApiInterface $variableApi |
384
|
|
|
) { |
385
|
|
|
$form = $this->createForm(SearchUserType::class, []); |
386
|
|
|
$form->handleRequest($request); |
387
|
|
|
if ($form->isSubmitted()) { |
388
|
|
|
$resultsForm = $this->createForm(DeleteType::class, [], [ |
389
|
|
|
'choices' => $userRepository->queryBySearchForm($form->getData()), |
390
|
|
|
'action' => $this->generateUrl('zikulausersmodule_useradministration_delete') |
391
|
|
|
]); |
392
|
|
|
|
393
|
|
|
return $this->render('@ZikulaUsersModule/UserAdministration/searchResults.html.twig', [ |
394
|
|
|
'resultsForm' => $resultsForm->createView(), |
395
|
|
|
'mailForm' => $this->buildMailForm($variableApi)->createView() |
396
|
|
|
]); |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
return [ |
400
|
|
|
'form' => $form->createView() |
401
|
|
|
]; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* @Route("/mail") |
406
|
|
|
* @PermissionCheck({"$_zkModule::MailUsers", "::", "comment"}) |
407
|
|
|
*/ |
408
|
|
|
public function mailUsersAction( |
409
|
|
|
Request $request, |
410
|
|
|
UserRepositoryInterface $userRepository, |
411
|
|
|
VariableApiInterface $variableApi, |
412
|
|
|
MailHelper $mailHelper |
413
|
|
|
): RedirectResponse { |
414
|
|
|
$mailForm = $this->buildMailForm($variableApi); |
415
|
|
|
$mailForm->handleRequest($request); |
416
|
|
|
if ($mailForm->isSubmitted() && $mailForm->isValid()) { |
417
|
|
|
$data = $mailForm->getData(); |
418
|
|
|
$users = $userRepository->query(['uid' => ['operator' => 'in', 'operand' => explode(',', $data['userIds'])]]); |
419
|
|
|
if (empty($users)) { |
420
|
|
|
throw new InvalidArgumentException($this->trans('No users found.')); |
421
|
|
|
} |
422
|
|
|
if ($mailHelper->mailUsers($users, $data)) { |
423
|
|
|
$this->addFlash('success', 'Done! Mail sent.'); |
424
|
|
|
} else { |
425
|
|
|
$this->addFlash('error', 'Could not send mail.'); |
426
|
|
|
} |
427
|
|
|
} else { |
428
|
|
|
$this->addFlash('error', 'Could not send mail.'); |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
return $this->redirectToRoute('zikulausersmodule_useradministration_search'); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
private function buildMailForm(VariableApiInterface $variableApi): FormInterface |
435
|
|
|
{ |
436
|
|
|
return $this->createForm(MailType::class, [ |
437
|
|
|
'from' => $variableApi->getSystemVar('sitename'), |
438
|
|
|
'replyto' => $variableApi->getSystemVar('adminmail'), |
439
|
|
|
'format' => 'text', |
440
|
|
|
'batchsize' => 100 |
441
|
|
|
], [ |
442
|
|
|
'action' => $this->generateUrl('zikulausersmodule_useradministration_mailusers') |
443
|
|
|
]); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Prevent user from modifying certain aspects of self. |
448
|
|
|
*/ |
449
|
|
|
private function checkSelf( |
450
|
|
|
CurrentUserApiInterface $currentUserApi, |
451
|
|
|
VariableApiInterface $variableApi, |
452
|
|
|
UserEntity $userBeingModified, |
453
|
|
|
array $originalGroups = [] |
454
|
|
|
): void { |
455
|
|
|
$currentUserId = $currentUserApi->get('uid'); |
456
|
|
|
if ($currentUserId !== $userBeingModified->getUid()) { |
457
|
|
|
return; |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
// current user not allowed to deactivate self |
461
|
|
|
if (UsersConstant::ACTIVATED_ACTIVE !== $userBeingModified->getActivated()) { |
462
|
|
|
$this->addFlash('info', 'You are not allowed to alter your own active state.'); |
463
|
|
|
$userBeingModified->setActivated(UsersConstant::ACTIVATED_ACTIVE); |
464
|
|
|
} |
465
|
|
|
// current user not allowed to remove self from default group |
466
|
|
|
$defaultGroup = $variableApi->get('ZikulaGroupsModule', 'defaultgroup', 1); |
467
|
|
|
if (!$userBeingModified->getGroups()->containsKey($defaultGroup)) { |
468
|
|
|
$this->addFlash('info', 'You are not allowed to remove yourself from the default group.'); |
469
|
|
|
$userBeingModified->getGroups()->add($originalGroups[$defaultGroup]); |
470
|
|
|
} |
471
|
|
|
// current user not allowed to remove self from admin group if currently a member |
472
|
|
|
if (isset($originalGroups[Constant::GROUP_ID_ADMIN]) && !$userBeingModified->getGroups()->containsKey(Constant::GROUP_ID_ADMIN)) { |
473
|
|
|
$this->addFlash('info', 'You are not allowed to remove yourself from the primary administrator group.'); |
474
|
|
|
$userBeingModified->getGroups()->add($originalGroups[Constant::GROUP_ID_ADMIN]); |
475
|
|
|
} |
476
|
|
|
} |
477
|
|
|
} |
478
|
|
|
|