UsersController::deleteAction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 0
cts 20
cp 0
rs 9.504
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
namespace Kunstmaan\UserManagementBundle\Controller;
4
5
use Doctrine\ORM\EntityManager;
6
use FOS\UserBundle\Event\UserEvent;
7
use FOS\UserBundle\Model\UserInterface;
8
use FOS\UserBundle\Model\UserManager;
9
use Kunstmaan\AdminBundle\Controller\BaseSettingsController;
10
use Kunstmaan\AdminBundle\Entity\BaseUser;
11
use Kunstmaan\AdminBundle\Event\AdaptSimpleFormEvent;
12
use Kunstmaan\AdminBundle\Event\Events;
13
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
14
use Kunstmaan\AdminBundle\Form\RoleDependentUserFormInterface;
15
use Kunstmaan\AdminListBundle\AdminList\AdminList;
16
use Kunstmaan\UserManagementBundle\Event\AfterUserDeleteEvent;
17
use Kunstmaan\UserManagementBundle\Event\UserEvents;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
19
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
20
use Symfony\Component\HttpFoundation\RedirectResponse;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
23
use Symfony\Component\Routing\Annotation\Route;
24
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
25
26
/**
27
 * Settings controller handling everything related to creating, editing, deleting and listing users in an admin list
28
 */
29
class UsersController extends BaseSettingsController
30
{
31
    /**
32
     * List users
33
     *
34
     * @Route("/", name="KunstmaanUserManagementBundle_settings_users")
35
     * @Template("@KunstmaanAdminList/Default/list.html.twig")
36
     *
37
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,AdminList>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
38
     */
39
    public function listAction(Request $request)
40
    {
41
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
42
43
        $em = $this->getDoctrine()->getManager();
44
        $configuratorClassName = '';
45
        if ($this->container->hasParameter('kunstmaan_user_management.user_admin_list_configurator.class')) {
46
            $configuratorClassName = $this->container->getParameter(
47
                'kunstmaan_user_management.user_admin_list_configurator.class'
48
            );
49
        }
50
51
        $configurator = new $configuratorClassName($em);
52
53
        /* @var AdminList $adminList */
54
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createList($configurator);
55
        $adminList->bindRequest($request);
56
57
        return [
58
            'adminlist' => $adminList,
59
        ];
60
    }
61
62
    /**
63
     * Get an instance of the admin user class.
64
     *
65
     * @return BaseUser
66
     */
67
    private function getUserClassInstance()
68
    {
69
        $userClassName = $this->container->getParameter('fos_user.model.user.class');
70
71
        return new $userClassName();
72
    }
73
74
    /**
75
     * Add a user
76
     *
77
     * @Route("/add", name="KunstmaanUserManagementBundle_settings_users_add", methods={"GET", "POST"})
78
     * @Template("@KunstmaanUserManagement/Users/add.html.twig")
79
     *
80
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be RedirectResponse|array<s...omponent\Form\FormView>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
81
     */
82
    public function addAction(Request $request)
83
    {
84
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
85
86
        $user = $this->getUserClassInstance();
87
88
        $options = ['password_required' => true, 'langs' => $this->container->getParameter('kunstmaan_admin.admin_locales'), 'validation_groups' => ['Registration'], 'data_class' => \get_class($user)];
89
        $formTypeClassName = $user->getFormTypeClass();
90
        $formType = new $formTypeClassName();
91
92
        if ($formType instanceof RoleDependentUserFormInterface) {
93
            // to edit groups and enabled the current user should have ROLE_SUPER_ADMIN
94
            $options['can_edit_all_fields'] = $this->isGranted('ROLE_SUPER_ADMIN');
95
        }
96
97
        $form = $this->createForm(
98
            $formTypeClassName,
99
            $user,
100
            $options
101
        );
102
103
        if ($request->isMethod('POST')) {
104
            $form->handleRequest($request);
105
            if ($form->isSubmitted() && $form->isValid()) {
106
                $user->setPasswordChanged(true);
107
                $user->setCreatedBy($this->getUser()->getUsername());
108
                /* @var UserManager $userManager */
109
                $userManager = $this->container->get('fos_user.user_manager');
110
                $userManager->updateUser($user, true);
0 ignored issues
show
Unused Code introduced by
The call to UserManager::updateUser() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
111
112
                $this->addFlash(
113
                    FlashTypes::SUCCESS,
114
                    $this->container->get('translator')->trans('kuma_user.users.add.flash.success.%username%', [
115
                        '%username%' => $user->getUsername(),
116
                    ])
117
                );
118
119
                return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
120
            }
121
        }
122
123
        return [
124
            'form' => $form->createView(),
125
        ];
126
    }
127
128
    /**
129
     * Edit a user
130
     *
131
     * @param int $id
132
     *
133
     * @Route("/{id}/edit", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_edit", methods={"GET", "POST"})
134
     * @Template("@KunstmaanUserManagement/Users/edit.html.twig")
135
     *
136
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be RedirectResponse|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
137
     *
138
     * @throws AccessDeniedException
139
     */
140
    public function editAction(Request $request, $id)
141
    {
142
        // The logged in user should be able to change his own password/username/email and not for other users
143
        if ($id == $this->container->get('security.token_storage')->getToken()->getUser()->getId()) {
144
            $requiredRole = 'ROLE_ADMIN';
145
        } else {
146
            $requiredRole = 'ROLE_SUPER_ADMIN';
147
        }
148
        $this->denyAccessUnlessGranted($requiredRole);
149
150
        /* @var EntityManager $em */
151
        $em = $this->getDoctrine()->getManager();
152
153
        /** @var UserInterface $user */
154
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
155
        if ($user === null) {
156
            throw new NotFoundHttpException(sprintf('User with ID %s not found', $id));
157
        }
158
159
        $userEvent = new UserEvent($user, $request);
160
        $this->dispatch($userEvent, UserEvents::USER_EDIT_INITIALIZE);
161
162
        $options = ['password_required' => false, 'langs' => $this->container->getParameter('kunstmaan_admin.admin_locales'), 'data_class' => \get_class($user)];
163
        $formFqn = $user->getFormTypeClass();
164
        $formType = new $formFqn();
165
166
        if ($formType instanceof RoleDependentUserFormInterface) {
167
            // to edit groups and enabled the current user should have ROLE_SUPER_ADMIN
168
            $options['can_edit_all_fields'] = $this->isGranted('ROLE_SUPER_ADMIN');
169
        }
170
171
        $event = new AdaptSimpleFormEvent($request, $formFqn, $user, $options);
172
        $event = $this->dispatch($event, Events::ADAPT_SIMPLE_FORM);
173
        $tabPane = $event->getTabPane();
174
175
        $form = $this->createForm($formFqn, $user, $options);
176
177
        if ($request->isMethod('POST')) {
178
            if ($tabPane) {
179
                $tabPane->bindRequest($request);
180
                $form = $tabPane->getForm();
181
            } else {
182
                $form->handleRequest($request);
183
            }
184
185
            if ($form->isSubmitted() && $form->isValid()) {
186
                /* @var UserManager $userManager */
187
                $userManager = $this->container->get('fos_user.user_manager');
188
                $userManager->updateUser($user, true);
0 ignored issues
show
Unused Code introduced by
The call to UserManager::updateUser() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
189
190
                $this->addFlash(
191
                    FlashTypes::SUCCESS,
192
                    $this->container->get('translator')->trans('kuma_user.users.edit.flash.success.%username%', [
193
                        '%username%' => $user->getUsername(),
194
                    ])
195
                );
196
197
                return new RedirectResponse(
198
                    $this->generateUrl(
199
                        'KunstmaanUserManagementBundle_settings_users_edit',
200
                        ['id' => $id]
201
                    )
202
                );
203
            }
204
        }
205
206
        $params = [
207
            'form' => $form->createView(),
208
            'user' => $user,
209
        ];
210
211
        if ($tabPane) {
212
            $params = array_merge($params, ['tabPane' => $tabPane]);
213
        }
214
215
        return $params;
216
    }
217
218
    /**
219
     * Delete a user
220
     *
221
     * @param Request $request
222
     * @param int     $id
223
     *
224
     * @Route("/{id}/delete", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_delete", methods={"POST"})
225
     *
226
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be RedirectResponse?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
227
     *
228
     * @throws AccessDeniedException
229
     *
230
     * @deprecated this method is deprecated since KunstmaanUserManagementBundle 5.6 and will be removed in KunstmaanUserManagementBundle 6.0
231
     */
232
    public function deleteAction(Request $request, $id)
233
    {
234
        @trigger_error('Using the deleteAction method from the UsersController is deprecated since KunstmaanUserManagementBundle 5.6 and will be replaced by the method deleteFormAction in KunstmaanUserManagementBundle 6.0. Use the correct method instead.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
235
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
236
237
        /* @var EntityManager $em */
238
        $em = $this->getDoctrine()->getManager();
239
        /* @var UserInterface $user */
240
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
241
        if (!\is_null($user)) {
242
            $userEvent = new UserEvent($user, $request);
243
            $this->dispatch($userEvent, UserEvents::USER_DELETE_INITIALIZE);
244
245
            $em->remove($user);
246
            $em->flush();
247
248
            $this->addFlash(
249
                FlashTypes::SUCCESS,
250
                $this->container->get('translator')->trans('kuma_user.users.delete.flash.success.%username%', [
251
                    '%username%' => $user->getUsername(),
252
                ])
253
            );
254
        }
255
256
        return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
257
    }
258
259
    /**
260
     * @Route("/form-delete/{id}", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_form_delete", methods={"POST"})
261
     */
262
    public function deleteFormAction(Request $request, $id)
263
    {
264
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
265
266
        $submittedToken = $request->request->get('token');
267
        if (!$this->isCsrfTokenValid('delete-user', $submittedToken)) {
268
            return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
269
        }
270
271
        /* @var EntityManager $em */
272
        $em = $this->getDoctrine()->getManager();
273
        /* @var UserInterface $user */
274
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
275
        if (!\is_null($user)) {
276
            $userEvent = new UserEvent($user, $request);
277
            $afterDeleteEvent = new AfterUserDeleteEvent($user->getUsername(), $this->getUser()->getUsername());
278
            $this->dispatch($userEvent, UserEvents::USER_DELETE_INITIALIZE);
279
280
            $em->remove($user);
281
            $em->flush();
282
283
            $this->dispatch($afterDeleteEvent, UserEvents::AFTER_USER_DELETE);
284
285
            $this->addFlash(
286
                FlashTypes::SUCCESS,
287
                $this->container->get('translator')->trans('kuma_user.users.delete.flash.success.%username%', [
288
                    '%username%' => $user->getUsername(),
289
                ])
290
            );
291
        }
292
293
        return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
294
    }
295
296
    /**
297
     * @return \Symfony\Component\HttpFoundation\Response
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use RedirectResponse.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
298
     */
299
    public function changePasswordAction()
300
    {
301
        // Redirect to current user edit route...
302
        return new RedirectResponse(
303
            $this->generateUrl(
304
                'KunstmaanUserManagementBundle_settings_users_edit',
305
                [
306
                    'id' => $this->container->get('security.token_storage')->getToken()->getUser()->getId(),
307
                ]
308
            )
309
        );
310
    }
311
312
    /**
313
     * @param object $event
314
     * @param string $eventName
315
     *
316
     * @return object
317
     */
318 View Code Duplication
    private function dispatch($event, string $eventName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
319
    {
320
        $eventDispatcher = $this->container->get('event_dispatcher');
321
        if (class_exists(LegacyEventDispatcherProxy::class)) {
322
            $eventDispatcher = LegacyEventDispatcherProxy::decorate($eventDispatcher);
323
324
            return $eventDispatcher->dispatch($event, $eventName);
325
        }
326
327
        return $eventDispatcher->dispatch($eventName, $event);
328
    }
329
}
330