Update user profile programmatically - Drupal 8

Drupal 8: I was afraid of it but when I start working in it, it's really a cool CMS than the previous version aka Drupal 7. Most of the things are depends on libraries means you need to include required library files in your controller or .module file or etc. and do your work. So I was working on a project in which the client wants to update user data with profile picture programmatically. So here are the steps which I have followed:

  1. Create a custom module with extension custom_module.info.yml file under module->custom-->custom_module and added the required entries in it:
    name: Custom module
    description: 'Custom module for all custom operations.'
    package: 'Custom'
    type: module core: 8.x 
  2. Now create a custom_moduel.routing.yml file and put it under your costom_module root directory. Basically, this file is used to define path or routing where our page or form will display and put this below code in it:
    custom_module.userprofileupdateform:
      path: user/{user}/user-profile-update
      defaults:
        _title: 'User profile'
        _form: '\Drupal\custom_module\Form\UserProfileUpdateForm'
      requirements: _permission: 'access content' 

    In above code path: user/{user}/social-profile is to define dynamic path for user's profile and _controller: '\Drupal\custom_module\Controller\UserProfileUpdateForm'

  3. Now create form controller file (which you have define in your above custom_module.routing.yml file) under modules->custom->custom_module->src->Form->UserProfileUpdateForm.php. This file is used to create a custom form with validation and submit handler. Note: The form controller class name, controller file name should be same as defined in the routing.yml file otherwise it will give an error.

    <?php
    /**
     * @file
     * Contains \Drupal\custom_module\Form\UserProfileUpdateForm.
     */
    namespace Drupal\custom_module\Form;
    
    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\user\Entity\User;
    use Drupal\Core\Url;
    use Drupal\file\Entity\File;
    use Drupal\Core\Ajax\AjaxResponse;
    use Drupal\Core\Ajax\HtmlCommand;
    use Drupal\Core\Ajax\InvokeCommand;
    use Drupal\media_entity_123rf\ME123rfBrowser;
    use Symfony\Component\HttpFoundation\Request;
    
    class UserProfileUpdateForm extends FormBase {
    
    /**
     * {@inheritdoc}
     */
    public function getFormId() {
      return 'user_profile_update';
    }
    
    /**
     *
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state) {
      $user = User::load(\Drupal::currentUser()->id());
      $firstname = $user->get('field_first_name')->value; 
      $lastname = $user->get('field_last_name')->value; 
      $email = $user->get('mail')->value; 
      $current_status = $user->get('field_current_status')->value; 
      $screen_name = $user->get('field_screen_name')->value; 
      $form['profile_image'] = array( 
        '#type' => 'managed_file', 
        '#name' =>'user_img', 
        '#title' => t('Profile Image'), 
        '#size' => 20, 
        '#description' => t('png, gif, jpg, jpeg format only'), 
        //'#upload_validators' => $validators, 
        '#upload_location' => 'public://pictures', 
        '#default_value' => $user->get('user_picture')->target_id, ); 
      
      $form['firstname'] = array( 
        '#type' => 'textfield', 
        '#title' => t('First Name:'), 
        '#required' => TRUE, 
        '#default_value' => $firstname,
      ); 
     
      $form['lastname'] = array( 
        '#type' => 'textfield', 
        '#title' => t('Last Name:'), 
        '#required' => TRUE, 
        '#default_value' => $lastname,
      ); 
    
      $form['screenname'] = array( 
        '#type' => 'textfield', 
        '#title' => t('Screen name:'), 
        '#required' => TRUE, 
        '#default_value' => $screen_name, 
      ); 
    
      $form['account']['pass'] = array( 
        '#type' => 'password_confirm', 
        '#size' => 25, 
        '#description' => $this->t('Provide a password for the new account in both fields.'),
      ); 
    
      $form['current_status'] = array ( 
        '#type' => 'select', 
        '#title' => ('Current Status:'), 
        '#options' => array( 
          'student' => t('Student'), 
          'paralegal' => t('Paralegal'), 
          'trainee' => t('Trainee'), 
          'qualified_lawyer' => t('Qualified Lawyer'), 
          'non_lawyer' => t('Non-Lawyer'), ), 
          '#default_value' => $current_status, 
      ); 
    
      $form['actions']['#type'] = 'actions'; 
      $form['actions']['submit'] = array( 
        '#type' => 'submit', 
        '#value' => $this->t('Update'),
        '#button_type' => 'primary', 
      ); 
    
      return $form; 
    } 
    
    /** 
     * {@inheritdoc} 
     * Form validation function to validate the form values 
     */ 
    // public function validateForm(array &$form, FormStateInterface $form_state) { 
    // }
    
    /** 
     * {@inheritdoc} 
     */ 
    public function submitForm(array &$form, FormStateInterface $form_state) { 
      //load current user 
      $user = User::load(\Drupal::currentUser()->id()); 
    
      //update password field value 
      if($password != NULL) { 
        $user->setPassword($password); 
      } 
      $user->set('user_picture', $form_state->getValue('profile_image')); 
      $user->set('field_first_name', $form_state->getValue('firstname')); 
      $user->set('field_last_name', $form_state->getValue('lastname')); 
      $user->set('field_current_status', $form_state->getValue('current_status')); 
      $user->set('field_screen_name', $form_state->getValue('screenname')); 
      //save user data 
      $user->save(); 
      $redirect_path = '/user/' . \Drupal::currentUser()->id(); 
      $url = url::fromUserInput($redirect_path); 
      // Set redirect 
      $form_state->setRedirectUrl($url); 
      }
    } 
    ?>
    
  4. Now save your custom_module and check logged in as a current user. Now go to this URL user/your_user_id/user-profile-update and you can see the desired form with the current user id.
    Note: There is some field which you have to define in the user account section to update in your custom_form.