0
votes

I'm running Symfony 3.4.14 and I developed my own User Bundle, I have a very bad experience with FOS then I don't want to use anymore. My goal is to let the admin users create/edit/remove users, I mean other users account.

I made :

  • the User entity
  • the Login form
  • the Registration form

.. and I'm stuck with the Update form. I want to let the admins edit a user without editing the password, but to give them the opportunity to do it if needed. Below is my EditUserAction in controller :

<?php

    /**
    * @Route("/admin/users/edit/{id}", requirements={"id" = "\d+"}, name="admin_users_edit")
    * @Template("@Core/admin/users_edit.html.twig")
    * @Security("has_role('ROLE_ADMIN')")
    */
    public function EditUserAction($id, Request $request, UserPasswordEncoderInterface $passwordEncoder)
    {
        $user = $this->getDoctrine()->getRepository('CoreBundle:User')->findOneBy([ 'id'=>$id, 'deleted' => 0 ]);
        if ( $user )
        {
            $old_password = $user->getPassword();
            $form = $this->createForm(UserType::class, $user);
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid())
            {
                // If admin changed the user password
                if ( $user->getPlainPassword() )
                {
                    $password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
                    $user->setPassword($password);
                }
                // If admin didn't change the user password, we persist the old one
                else
                {
                    $user->setPassword($old_password);
                }
                $entityManager = $this->getDoctrine()->getManager();
                $entityManager->persist($user);
                $entityManager->flush();
            }
            return array('form' => $form->createView());
        }
        return $this->redirectToRoute('admin_users');
    }

Case 1 (when admin choose to change the user password) works well, but the other case (when admin don't want to change the password) fails. They are no way to let the 2 password inputs empty. I can't get rid of this validation error in the debug toolbar :

Path: data.plainPassword
Message: This value should not be blank

In order to avoid this error, as you can see in my controller above, I try to keep the old one (may not be a best practice, I know).

2
To resolve your problem just use Validation Groups. A bit off-topic but an admin should never be able to change the user password but only show a reminder where the user will be forced to change it. - gp_sflover
make two separate actions: 1. will edit user info without password 2. set user password - Denis Alimov
@gp_sflover It's a startup intranet website, so there is no issue for admins to change the password user ;) On your advice, i'm going to check Validation groups. Thanks ! - Paolito75
@DenisAlimov I also thought about it but I believe this is not the more "user friendly" solution ;) - Paolito75
to get rid of the validation message the password field shouln't be required, you can pass a flag on createForm function to change required attr to false or true - Abdelhafid El Kadiri

2 Answers

0
votes

In your form / entity (where you defined validations) you should write either your own constraint (documentation) or validation callback (documentation). In there you can check - If value is null, don't validate, if not null run your validations.

0
votes

You need to have two separate methods for both.

public function changePasswordAction(Request $request)
 {
  // your code for changing password. 
 }

 /**
 * @Route("/admin/users/edit/{id}", requirements={"id" = "\d+"},     name="admin_users_edit")
 * @Template("@Core/admin/users_edit.html.twig")
 * @Security("has_role('ROLE_ADMIN')")
 */
public function editUserAction(User $user = null, Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
    //you can directly give your User Entity reference in parameters and you dont need to write an extra query to find user. 

    if ( $user === null){
        //return user not found
    }
    else if($user->isDeleted() === false)
    {
        $form = $this->createForm(UserType::class, $user);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid())
        {
            //your code
        }
        // your code
    }
    return $this->redirectToRoute('admin_users');
}