web-dev-qa-db-fra.com

Remplacer le formulaire d'inscription d'utilisateur

Je cherche un OOP moyen d'avoir un formulaire d'inscription utilisateur simplifié dans Drupal 8.

À ce jour, le formulaire d'inscription utilisateur par défaut est déclaré directement en tant qu'annotation dans la classe Utilisateur. Depuis les pages d'administration, il est possible d'ajouter un affichage de formulaire Register pour le formulaire utilisateur. Cependant, lors de la suppression de tous les champs possibles, sauf pour le mot de passe/connexion, il y a encore un tas de champs qui apparaissent que je souhaite supprimer:

  • Username
  • Confirmation mot de passe
  • Paramètres régionaux
  • Paramètres de contact
  • etc.

Ce que je veux, c'est un formulaire d'inscription extrêmement simple, avec seulement deux champs: adresse e-mail et mot de passe. Tous les autres champs seront modifiables ultérieurement. Je veux que ce formulaire utilise OOP si possible, donc étendre la classe Drupal\user\RegisterForm me semble un bon moyen d'y parvenir ...

J'ai étendu le formulaire mais je ne peux pas l'utiliser. Cela nécessite apparemment qu'une entité lui soit transmise, mais je ne sais pas comment faire.

La façon idéale de le faire serait:

$entity = \Drupal::entityTypeManager()
  ->getStorage('user')
  ->create([])
;
$formObject = \Drupal::entityTypeManager()
  ->getFormObject('user', 'register')
  ->setEntity($entity)
;
$registerForm = \Drupal::formBuilder()->getForm($formObject);

Cependant, cela exigera de récupérer la classe originale, non héritée RegisterForm, pas ma classe personnalisée. Comment puis-je dire à Drupal d'instancier mon propre formulaire à la place?

BTW comment puis-je rendre nom d'utilisateur facultatif?

J'ai vu quelques solutions pour redéfinir le formulaire d'inscription d'utilisateur, mais la plupart d'entre elles sont Drupal 7 solutions et aucune d'entre elles n'est OOP.

4
Zephyr

Si vous souhaitez utiliser la classe de formulaire de registre étendu, vous devez la mettre à la place de la classe de formulaire d'origine dans le type d'entité utilisateur:

mymodule.module

  /**
   * Implements hook_entity_type_alter().
   */
  function mymodule_entity_type_alter(array &$entity_types) {
    $entity_types['user']->setFormClass('register', 'Drupal\mymodule\MyRegisterForm');
  }
5
4k4

Vous devez créer un module personnalisé et ajouter un service:

@file: my_module.services.yml

  services:
    route_subscriber:
      class: Drupal\my_module\Routing\RouteSubscriber
      tags:
        - {name: event_subscriber }

@file: src/Routing/RouteSubscriber.php

  /**
   * @file
   * Contains \Drupal\my_module\Routing\RouteSubscriber.
   */

  namespace Drupal\my_module\Routing;

  use Drupal\Core\Routing\RouteSubscriberBase;
  use Symfony\Component\Routing\RouteCollection;

  /**
   * Listens to the dynamic route events.
   */
  class RouteSubscriber extends RouteSubscriberBase {

    /**
     * {@inheritdoc}
     */
    protected function alterRoutes(RouteCollection $collection) {
      // login form
      if ($route = $collection->get('user.login')) {
        $route->setDefault('_form', '\Drupal\my_module\Form\NewUserLoginForm');
      }
      // register form
      if ($route = $collection->get('user.register')) {
        $route->setDefault('_form', '\Drupal\my_module\Form\NewUserRegisterForm');
      }

    }
  }

et une classe de formulaire personnalisée:

@file: src/Form/NewUserRegisterForm.php

  /**
   * @file
   * Contains \Drupal\my_module\Form\NewUserRegisterForm.
   *
   * credits to: https://Gist.github.com/davidDuymelinck/cd20ab7049749358717127f12666b68c
   */

  namespace Drupal\my_module\Form;

  use Drupal\Component\Datetime\TimeInterface;
  use Drupal\Core\Entity\EntityFormBuilderInterface;
  use Drupal\Core\Entity\EntityManagerInterface;
  use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
  use Drupal\Core\Extension\ModuleHandlerInterface;
  use Drupal\Core\Form\FormStateInterface;
  use Drupal\Core\Language\LanguageManagerInterface;
  use Drupal\user\Entity\User;
  use Drupal\user\RegisterForm;
  use Symfony\Component\DependencyInjection\ContainerInterface;

  /**
   * Provides a user register form.
   */
  class NewUserRegisterForm extends RegisterForm {
      public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, ModuleHandlerInterface $moduleHandler) {
          $this->setEntity(new User([], 'user'));
          $this->setModuleHandler($moduleHandler);
          parent::__construct($entity_manager, $language_manager, $entity_type_bundle_info, $time);
      }
      /**
       * @inheritdoc
       */
      public static function create(ContainerInterface $container) {
          return new static(
              $container->get('entity.manager'),
              $container->get('language_manager'),
              $container->get('entity_type.bundle.info'),
              $container->get('datetime.time'),
              $container->get('module_handler')
          );
      }
      public function form(array $form, FormStateInterface $form_state) {
          $form = parent::form($form, $form_state);
          $form['test'] = [
              '#markup' => '<p>Test extended form</p>',
          ];

          return $form;
      }
  }

NB: Je n'ai pas trouvé comment altérer/modifier le bouton d'envoi car $form n'a pas de clé actions.

3
anou

J'utiliserais les ressources REST pour créer des utilisateurs au lieu de se connecter aux classes Drupal. C'est beaucoup plus facile et vos gars frontend peuvent contrôler complètement l'expérience d'enregistrement.

  1. Activer REST et REST UI
  2. Activer/user/register REST route
  3. Modifier les autorisations pour cet itinéraire en ajoutant "accès anonyme"
  4. Maintenant, vous envoyez des objets JSON à/user/register via ajax
  5. Exemple:

    $.ajax({
        url: Drupal.url('user/register?_format=json'),
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(userForm),
        headers: {
            'X-CSRF-Token': csrfToken,
            'Content-type': 'application/json'
        },
    }).done(function(response) {
      console.log('done')
      console.log(response)
    }).fail(function(jqXHR, textStatus) {
      console.log( JSON.parse(jqXHR.responseText))
    });
    
  6. Maintenant, votre formulaire d'inscription HTML est entièrement personnalisable.
2
Richard