Completed
Pull Request — master (#2743)
by Jeroen
16:52 queued 10:35
created

UsersController::getUserClassInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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 Kunstmaan\AdminBundle\Controller\BaseSettingsController;
9
use Kunstmaan\AdminBundle\Entity\BaseUser;
10
use Kunstmaan\AdminBundle\Event\AdaptSimpleFormEvent;
11
use Kunstmaan\AdminBundle\Event\Events;
12
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
13
use Kunstmaan\AdminBundle\Form\RoleDependentUserFormInterface;
14
use Kunstmaan\AdminListBundle\AdminList\AdminList;
15
use Kunstmaan\UserManagementBundle\Event\UserEvents;
16
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
17
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
18
use Symfony\Component\HttpFoundation\RedirectResponse;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
21
use Symfony\Component\Routing\Annotation\Route;
22
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
23
24
/**
25
 * Settings controller handling everything related to creating, editing, deleting and listing users in an admin list
26
 */
27
class UsersController extends BaseSettingsController
28
{
29
    /**
30
     * List users
31
     *
32
     * @Route("/", name="KunstmaanUserManagementBundle_settings_users")
33
     * @Template("@KunstmaanAdminList/Default/list.html.twig")
34
     *
35
     * @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...
36
     */
37
    public function listAction(Request $request)
38
    {
39
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
40
41
        $em = $this->getDoctrine()->getManager();
42
        $configuratorClassName = '';
43
        if ($this->container->hasParameter('kunstmaan_user_management.user_admin_list_configurator.class')) {
44
            $configuratorClassName = $this->container->getParameter(
45
                'kunstmaan_user_management.user_admin_list_configurator.class'
46
            );
47
        }
48
49
        $configurator = new $configuratorClassName($em);
50
51
        /* @var AdminList $adminList */
52
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createList($configurator);
53
        $adminList->bindRequest($request);
54
55
        return [
56
            'adminlist' => $adminList,
57
        ];
58
    }
59
60
    /**
61
     * Get an instance of the admin user class.
62
     *
63
     * @return BaseUser
64
     */
65
    private function getUserClassInstance()
66
    {
67
        $userClassName = $this->container->getParameter('fos_user.model.user.class');
68
69
        return new $userClassName();
70
    }
71
72
    /**
73
     * Add a user
74
     *
75
     * @Route("/add", name="KunstmaanUserManagementBundle_settings_users_add", methods={"GET", "POST"})
76
     * @Template("@KunstmaanUserManagement/Users/add.html.twig")
77
     *
78
     * @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...
79
     */
80
    public function addAction(Request $request)
81
    {
82
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
83
84
        $user = $this->getUserClassInstance();
85
86
        $options = ['password_required' => true, 'langs' => $this->container->getParameter('kunstmaan_admin.admin_locales'), 'validation_groups' => ['Registration'], 'data_class' => \get_class($user)];
87
        $formTypeClassName = $user->getFormTypeClass();
88
        $formType = new $formTypeClassName();
89
90
        if ($formType instanceof RoleDependentUserFormInterface) {
91
            // to edit groups and enabled the current user should have ROLE_SUPER_ADMIN
92
            $options['can_edit_all_fields'] = $this->isGranted('ROLE_SUPER_ADMIN');
93
        }
94
95
        $form = $this->createForm(
96
            $formTypeClassName,
97
            $user,
98
            $options
99
        );
100
101
        if ($request->isMethod('POST')) {
102
            $form->handleRequest($request);
103 View Code Duplication
            if ($form->isSubmitted() && $form->isValid()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
104
                $user->setPasswordChanged(true);
105
                /* @var UserManager $userManager */
106
                $userManager = $this->container->get('fos_user.user_manager');
107
                $userManager->updateUser($user, true);
108
109
                $this->addFlash(
110
                    FlashTypes::SUCCESS,
111
                    $this->container->get('translator')->trans('kuma_user.users.add.flash.success.%username%', [
112
                        '%username%' => $user->getUsername(),
113
                    ])
114
                );
115
116
                return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
117
            }
118
        }
119
120
        return [
121
            'form' => $form->createView(),
122
        ];
123
    }
124
125
    /**
126
     * Edit a user
127
     *
128
     * @param int $id
129
     *
130
     * @Route("/{id}/edit", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_edit", methods={"GET", "POST"})
131
     * @Template("@KunstmaanUserManagement/Users/edit.html.twig")
132
     *
133
     * @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...
134
     *
135
     * @throws AccessDeniedException
136
     */
137
    public function editAction(Request $request, $id)
138
    {
139
        // The logged in user should be able to change his own password/username/email and not for other users
140
        if ($id == $this->container->get('security.token_storage')->getToken()->getUser()->getId()) {
141
            $requiredRole = 'ROLE_ADMIN';
142
        } else {
143
            $requiredRole = 'ROLE_SUPER_ADMIN';
144
        }
145
        $this->denyAccessUnlessGranted($requiredRole);
146
147
        /* @var EntityManager $em */
148
        $em = $this->getDoctrine()->getManager();
149
150
        /** @var UserInterface $user */
151
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
152
        if ($user === null) {
153
            throw new NotFoundHttpException(sprintf('User with ID %s not found', $id));
154
        }
155
156
        $userEvent = new UserEvent($user, $request);
157
        $this->dispatch($userEvent, UserEvents::USER_EDIT_INITIALIZE);
158
159
        $options = ['password_required' => false, 'langs' => $this->container->getParameter('kunstmaan_admin.admin_locales'), 'data_class' => \get_class($user)];
160
        $formFqn = $user->getFormTypeClass();
161
        $formType = new $formFqn();
162
163
        if ($formType instanceof RoleDependentUserFormInterface) {
164
            // to edit groups and enabled the current user should have ROLE_SUPER_ADMIN
165
            $options['can_edit_all_fields'] = $this->isGranted('ROLE_SUPER_ADMIN');
166
        }
167
168
        $event = new AdaptSimpleFormEvent($request, $formFqn, $user, $options);
169
        $event = $this->dispatch($event, Events::ADAPT_SIMPLE_FORM);
170
        $tabPane = $event->getTabPane();
171
172
        $form = $this->createForm($formFqn, $user, $options);
173
174
        if ($request->isMethod('POST')) {
175
            if ($tabPane) {
176
                $tabPane->bindRequest($request);
177
                $form = $tabPane->getForm();
178
            } else {
179
                $form->handleRequest($request);
180
            }
181
182 View Code Duplication
            if ($form->isSubmitted() && $form->isValid()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
183
                /* @var UserManager $userManager */
184
                $userManager = $this->container->get('fos_user.user_manager');
185
                $userManager->updateUser($user, true);
186
187
                $this->addFlash(
188
                    FlashTypes::SUCCESS,
189
                    $this->container->get('translator')->trans('kuma_user.users.edit.flash.success.%username%', [
190
                        '%username%' => $user->getUsername(),
191
                    ])
192
                );
193
194
                return new RedirectResponse(
195
                    $this->generateUrl(
196
                        'KunstmaanUserManagementBundle_settings_users_edit',
197
                        ['id' => $id]
198
                    )
199
                );
200
            }
201
        }
202
203
        $params = [
204
            'form' => $form->createView(),
205
            'user' => $user,
206
        ];
207
208
        if ($tabPane) {
209
            $params = array_merge($params, ['tabPane' => $tabPane]);
210
        }
211
212
        return $params;
213
    }
214
215
    /**
216
     * Delete a user
217
     *
218
     * @param Request $request
219
     * @param int     $id
220
     *
221
     * @Route("/{id}/delete", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_delete", methods={"POST"})
222
     *
223
     * @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...
224
     *
225
     * @throws AccessDeniedException
226
     *
227
     * @deprecated this method is deprecated since KunstmaanUserManagementBundle 5.6 and will be removed in KunstmaanUserManagementBundle 6.0
228
     */
229
    public function deleteAction(Request $request, $id)
230
    {
231
        @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...
232
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
233
234
        /* @var EntityManager $em */
235
        $em = $this->getDoctrine()->getManager();
236
        /* @var UserInterface $user */
237
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
238 View Code Duplication
        if (!\is_null($user)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
239
            $userEvent = new UserEvent($user, $request);
240
            $this->dispatch($userEvent, UserEvents::USER_DELETE_INITIALIZE);
241
242
            $em->remove($user);
243
            $em->flush();
244
245
            $this->addFlash(
246
                FlashTypes::SUCCESS,
247
                $this->container->get('translator')->trans('kuma_user.users.delete.flash.success.%username%', [
248
                    '%username%' => $user->getUsername(),
249
                ])
250
            );
251
        }
252
253
        return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
254
    }
255
256
    /**
257
     * @Route("/form-delete/{id}", requirements={"id" = "\d+"}, name="KunstmaanUserManagementBundle_settings_users_form_delete", methods={"POST"})
258
     */
259
    public function deleteFormAction(Request $request, $id)
260
    {
261
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
262
263
        $submittedToken = $request->request->get('token');
264
        if (!$this->isCsrfTokenValid('delete-user', $submittedToken)) {
265
            return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
266
        }
267
268
        /* @var EntityManager $em */
269
        $em = $this->getDoctrine()->getManager();
270
        /* @var UserInterface $user */
271
        $user = $em->getRepository($this->container->getParameter('fos_user.model.user.class'))->find($id);
272 View Code Duplication
        if (!\is_null($user)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
273
            $userEvent = new UserEvent($user, $request);
274
            $this->dispatch($userEvent, UserEvents::USER_DELETE_INITIALIZE);
275
276
            $em->remove($user);
277
            $em->flush();
278
279
            $this->addFlash(
280
                FlashTypes::SUCCESS,
281
                $this->container->get('translator')->trans('kuma_user.users.delete.flash.success.%username%', [
282
                    '%username%' => $user->getUsername(),
283
                ])
284
            );
285
        }
286
287
        return new RedirectResponse($this->generateUrl('KunstmaanUserManagementBundle_settings_users'));
288
    }
289
290
    /**
291
     * @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...
292
     */
293
    public function changePasswordAction()
294
    {
295
        // Redirect to current user edit route...
296
        return new RedirectResponse(
297
            $this->generateUrl(
298
                'KunstmaanUserManagementBundle_settings_users_edit',
299
                [
300
                    'id' => $this->container->get('security.token_storage')->getToken()->getUser()->getId(),
301
                ]
302
            )
303
        );
304
    }
305
306
    /**
307
     * @param object $event
308
     * @param string $eventName
309
     *
310
     * @return object
311
     */
312 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...
313
    {
314
        $eventDispatcher = $this->container->get('event_dispatcher');
315
        if (class_exists(LegacyEventDispatcherProxy::class)) {
316
            $eventDispatcher = LegacyEventDispatcherProxy::decorate($eventDispatcher);
317
318
            return $eventDispatcher->dispatch($event, $eventName);
319
        }
320
321
        return $eventDispatcher->dispatch($eventName, $event);
322
    }
323
}
324