Học cách One way is to create a Settings webform handler

28th Jun 2022
Table of contents

Case 1

Webform custom handler response

namespace Drupal\my_module\Plugin\WebformHandler;

use Drupal\webform\Plugin\WebformHandler\SettingsWebformHandler;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Dynamic confirm message.
 *
 * @WebformHandler(
 *   id = "dynamic_confirm_message",
 *   label = @Translation("Dynamic confirm message"),
 *   category = @Translation("Settings"),
 *   description = @Translation("Change confirmation message after form submission"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
 * )
 */
class ConfirmMessageSettingsWebformHandler extends SettingsWebformHandler {
 
  public function overrideSettings(array &$settings, WebformSubmissionInterface $webform_submission) {
    $settings['confirmation_message'] = $this->t('My new confirmation message');
  }
}

But if you want to use the token, you can create a hidden element of the "value" type and populate in the webform handler. The screenshots of the example:

But if you want to use the token, you can create a hidden element of the "value" type and populate in the webform handler. The screenshots of the example:

Case 2

I have a Webform attached as a field to a specific content type.

After the node is loaded and the Webform is submitted, I am using the below custom webform handler to get the $webform_submission values.

<?php

namespace Drupal\my_custom_module\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;

use Drupal\node\Entity\Node;

use Drupal\webform\WebformInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;
use Drupal\webform\Entity\WebformSubmission;

/**
 * Do something when a webform submission is submitted.
 *
 * @WebformHandler(
 *   id = "Do something",
 *   label = @Translation("Do something"),
 *   category = @Translation("any category"),
 *   description = @Translation("Do something"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
 * )
 */

class customWebformHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */

  // Function to be fired while submitting the Webform.
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Get an array of the values from the submission.
    $values = $webform_submission->getData();

    // Get (Full Name) from (full_name) text element available on the webform.
    $fullnamevalue = $values["full_name"];

Case 3

Webform handler to manage number of places available when is possible to registrate more than 1 persone

I want to manage a webform to automatically close it if number of people reached, or to invalid submission if not enough places are available.

<?php
namespace Drupal\webform_reservations\Plugin\WebformHandler;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;

/**
 * Form submission handler.
 *
 * @WebformHandler(
 * id = "webform_reservations_handler",
 * label = @Translation("Reservations Handler"),
 * category = @Translation("Form Handler"),
 * description = @Translation("Manage maximum reservations by submission. Be Carfull some parameters are needed for working !"),
 * cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 * results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */

class ReservationHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */

  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    $webform = $webform_submission->getWebform();
    $formid = $webform->id();
    $event_max_people= $webform_submission->getElementData('event_max_people');

//query the db for all submissions of current webform submission
    $query = \Drupal::entityQuery('webform_submission');
    $query->condition('webform_id', $formid);
    $result = $query->execute();

//load all the submissions from the results
    $storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
    $submissions = $storage->loadMultiple($result);
    $submission_data = array();

    foreach ($submissions as $submission) {
      $submission_data[] = $submission->getData();
    }
    $current_reserved = 0;
//add up all the values in the 'number_of_people' field of each submission and save it to a variable.
    for ($i = 0; $i < count($submission_data); $i++){
      $current_reserved += $submission_data[$i]['number_of_people'];
    }

    if ($event_max_people <= $current_reserved) {
      // normally impossible state because the form automatically close when number of people is reached.
      // TODO : change the status of the form and not add this submission
      $webform->setStatus(WebformInterface::STATUS_CLOSED);
      $webform->save();
      $log_message = "The form is full, so it's now closed, but normally it should already have been closed!?";

    } elseif ( $event_max_people == $current_reserved + $webform_submission->getElementData('number_of_people')) {
      // just the number of people to close the registrations
      // TODO : So change form status to close and add the submission.
      $webform->setStatus(false);
      $webform->save();
      $log_message = "The form is full, so it's now closed. From " .$current_reserved. "/" .$event_max_people. " to ".($current_reserved+$webform_submission->getElementData('number_of_people')). "/" .$event_max_people . ".";

    } elseif ($event_max_people < $current_reserved + $webform_submission->getElementData('nombre_de_personnes')) {
      // Not enough places
      // TODO : No submission and go back to the form with a message
      $log_message = "There are only " . ($event_max_people-$current_reserved) ." places left so not enough for your ".$webform_submission->getElementData('number_of_people') ." requested places !";

    } else {
      // everything is ok, so nothing to do, only a message in the log
      $log_message = "The form had " .$current_reserved. "/" .$event_max_people. " people, and now, it has : ".($current_reserved+$webform_submission->getElementData('number_of_people')). "/" .$event_max_people . " people.";
    }

//log the output to the drupal logger, to indicate if the webform is still open or closed after each submission.
    \Drupal::logger('webform_reservations')->info($log_message);
  }
}

Case RegistrationFormHandler.php

<?php

namespace Drupal\webform_user_register\Plugin\WebformHandler;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\Plugin\WebformHandlerInterface;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\user\Entity\User;
use Drupal\Core\Form\FormStateInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Emails a WEB form submission.
 *
 * @WebformHandler(
 *   id = "registration",
 *   label = @Translation("Register user"),
 *   category = @Translation("Registration"),
 *   description = @Translation("Registers user and logs into Drupal."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */
class RegistrationFormHandler extends WebformHandlerBase implements WebformHandlerInterface {

  /**
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * @var \Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * RedirectHandler constructor.
   *
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param \Psr\Log\LoggerInterface $logger
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $logger, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $currentUser, RequestStack $requestStack) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $logger, $config_factory, $entity_type_manager);
    $this->currentUser = $currentUser;
    $this->request = $requestStack->getCurrentRequest();
  }

  /**
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @return static
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.factory')->get('webform'),
      $container->get('config.factory'),
      $container->get('entity_type.manager'),
      $container->get('current_user'),
      $container->get('request_stack')
    );
  }

  /**
   * {@inheritdoc}
   */
  protected function getConfigurationSettings() {
    $mapping = array();
    $entityManager = \Drupal::service('entity.manager');
    $fields = $entityManager->getFieldDefinitions('user', 'user');
    foreach ($fields as $fieldId => $field) {
      $mapping[$fieldId] = array(
        'type' => 'select',
        'required' => ($fieldId == 'mail') ? TRUE : FALSE,
        'label' => $field->getLabel(),
      );
    }
    return $mapping;
  }

  /**
   * @return mixed
   */
  protected function getUserProfileFields() {
    $entityManager = \Drupal::service('entity.manager');
    $fields = $entityManager->getFieldDefinitions('user', 'user');
    $mapping[] = $this->t('-- Choose user field --');
    foreach ($fields as $fieldId => $field) {
      $mapping[$fieldId] = $field->getLabel();
    }
    return $mapping;
  }

  /**
   * Get the list of Web form fields with labels
   *
   * @return array
   */
  private function getWebformFieldsWithLabels() {
    $options = array();
    $webform = $this->getWebform()->getElementsDecodedAndFlattened();
    foreach ($webform as $key => $element) {
      if (in_array($element['#type'], array(
        'textfield',
        'tel',
        'email',
        'select',
        'checkbox',
        'radios',
        'value'
      ))) {
        if (!empty($element['#title'])) {
          $options[$key] = $element['#title'];
        }
        else {
          $options[$key] = $key;
        }
      }
    }
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $settings = $this->getConfigurationSettings();
    $options = array('' => $this->t('Choose mapping element from Webform'));
    $webform = $this->getWebform()->getElementsDecodedAndFlattened();
    foreach ($webform as $key => $element) {
      if (in_array($element['#type'], array(
        'textfield',
        'textarea',
        'tel',
        'email',
        'select',
        'checkbox',
        'radios',
        'value'
      ))) {
        if ($element['#type'] == 'value') {
          $options[$key] = $key;
        }
        else {
          $options[$key] = $element['#title'];
        }
      }
    }
    $form['mapping'] = array(
      '#type' => 'details',
      '#title' => $this->t('Fields mapping'),
      '#open' => FALSE,
    );
    foreach ($settings as $config_name => $config_settings) {
      $type = $config_settings['type'];
      $mode = isset($config_settings['mode']) ? $config_settings['mode'] : NULL;
      $label = $config_settings['label'];
      $required = $config_settings['required'];
      $form['mapping'][$config_name] = array(
        '#type' => $type,
        '#mode' => $mode,
        '#title' => $label,
        '#options' => $options,
        '#required' => $required,
        '#default_value' => $this->configuration[$config_name],
      );
    }
    $roles = array_map(array(
      '\Drupal\Component\Utility\Html',
      'escape'
    ), user_role_names(TRUE));
    $form['user_role'] = array(
      '#type' => 'select',
      '#title' => $this->t('User default role'),
      '#default_value' => $this->configuration['user_role'],
      '#options' => $roles,
    );
    $form['update_user'] = array(
      '#type' => 'checkbox',
      '#title' => $this->t('Update existing user information'),
      '#default_value' => $this->configuration['update_user'],
      '#return_value' => 1,
    );
    $form['skip_update'] = array(
      '#type' => 'select',
      '#multiple' => TRUE,
      '#size' => 10,
      '#title' => $this->t('Skip selected fields during update'),
      '#default_value' => $this->configuration['skip_update'],
      '#options' => $this->getUserProfileFields(),
      '#states' => array(
        'visible' => array(
          ':input[name="settings[update_user]"]' => array('checked' => TRUE),
        ),
      ),
    );
    $form['send_mail'] = array(
      '#type' => 'checkbox',
      '#title' => $this->t('Send the new user email'),
      '#default_value' => $this->configuration['send_mail'],
      '#return_value' => 1,
    );

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);

    // Get other settings.
    $values = $form_state->getValues();
    $this->configuration['user_role'] = $values['user_role'];
    $this->configuration['update_user'] = $values['update_user'];
    $this->configuration['send_mail'] = $values['send_mail'];
    $this->configuration['skip_update'] = $values['skip_update'];
    foreach ($values['mapping'] as $key => $mapping) {
      $this->configuration[$key] = $mapping;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getSummary() {
    $summary = [
        '#settings' => $this->getRegistrationConfiguration(),
        '#user_fields' => $this->getConfigurationSettings(),
        '#web_form' => $this->getWebformFieldsWithLabels(),
      ] + parent::getSummary();
    return $summary;
  }

  /**
   * Get mail configuration values.
   *
   * @return array
   *   An associative array containing email configuration values.
   */
  protected function getRegistrationConfiguration() {
    $configuration = $this->getConfiguration();
    $registration = [];
    foreach ($configuration['settings'] as $key => $value) {
      if ($value != '') {
        $registration[$key] = $value;
      }
    }
    return $registration;
  }

  /**
   * {@inheritdoc}
   */
  public function preSave(WebformSubmissionInterface $webform_submission, $update = TRUE) {
    if ($webform_submission) {
      $data = $webform_submission->getData();
      if ($this->currentUser->isAuthenticated()) {
        $account = User::load($this->currentUser->id());
        $data['tuid'] = $account->uuid();
        $webform_submission->setData($data);
        return;
      }
      $mapping = $this->getRegistrationConfiguration();
      if (!empty($mapping) && !empty($mapping['mail'])) {
        $mail = $data[$mapping['mail']];
        unset($mapping['mail']);
        $user = $this->findUserByEmail($mail);
        $userNew = FALSE;
        if (!$user) {
          $userNew = TRUE;
          if (\Drupal::moduleHandler()->moduleExists('email_registration')) {
            // Strip off everything after the @ sign.
            $new_name = preg_replace('/@.*$/', '', $mail);
            // Clean up the username.
            $new_name = email_registration_cleanup_username($new_name);
            $userName = email_registration_unique_username($new_name);
          }
          else {
            $userName = $mail;
          }
          if (!empty($mapping['name'])) {
            $userName = $data[$mapping['name']];
            unset($mapping['name']);
          }
          $password = user_password(8);
          if (!empty($mapping['pass'])) {
            $password = $data[$mapping['pass']];
            unset($mapping['pass']);
          }
          $init = $mail;
          if (!empty($mapping['init'])) {
            $init = $data[$mapping['init']];
            unset($mapping['init']);
          }
          unset($mapping['user_role']);
          unset($mapping['update_user']);
          $user = $this->createUser($mail, $userName, $password, $init);
        }
        if ((!$userNew && $this->configuration['update_user']) || $userNew) {
          $skip_updates = $mapping['skip_update'];
          foreach ($mapping as $fieldName => $item) {
            if (!$userNew && !empty($skip_updates)) {
              if (in_array($fieldName, $skip_updates)) {
                continue;
              }
            }
            $value = '';
            if ($user->hasField($fieldName)) {
              if (is_string($item) && strpos($item, '::') !== FALSE) {
                $parts = explode('::', $item);
                if (!empty($data[$parts[0]][$parts[1]])) {
                  $value = $data[$parts[0]][$parts[1]];
                }
              }
              elseif (!empty($data[$item])) {
                $value = $data[$item];
              }
              $user->set($fieldName, $value);
            }
          }
          $user->save();
        }
        if ($user->id()) {
          $data['tuid'] = $user->uuid();
          $webform_submission->setData($data);
          $webform_submission->set('uid', $user->id());
          if ($this->configuration['send_mail'] && $userNew) {
            $user->password = $password;
            _user_mail_notify('register_no_approval_required', $user);
          }
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function postSave(WebformSubmissionInterface $webform_submission, $update = TRUE) {
    $is_completed = ($webform_submission->getState() == WebformSubmissionInterface::STATE_COMPLETED);
    if ($is_completed) {
      $account = User::load($webform_submission->getOwnerId());
      if (!$this->currentUser->id()) {
        user_login_finalize($account);
      }
    }
  }

  /**
   * Create a new user object
   *
   * @param $email
   * @param $userName
   * @param $password
   * @param $init
   * @return \Drupal\Core\Entity\EntityInterface|static
   */
  private function createUser($email, $userName, $password, $init) {
    $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $user = User::create();
    $user->setPassword($password);
    $user->enforceIsNew();
    $user->setEmail($email);
    $user->setUsername($userName);
    $user->set("init", $init);
    $user->set("langcode", $language);
    $user->set("preferred_langcode", $language);
    $user->set("preferred_admin_langcode", $language);
    if ($this->configuration['user_role'] != 'authenticated') {
      $user->addRole($this->configuration['user_role']);
    }
    $user->activate();

    return $user;
  }

  /**
   * @param $mail
   * @return bool|mixed
   */
  private function findUserByEmail($mail) {
    $query_service = \Drupal::service('entity.query');
    $query = $query_service->get('user');
    $query->condition('mail', $mail);
    $ids = $query->execute();
    if (!empty($ids)) {
      // Load multiple nodes
      $users = User::loadMultiple($ids);
      return reset($users);
    }
    return FALSE;
  }

  /**
   * Populate the default values for the fields in the form
   *
   * @param $elements
   * @param $account
   * @param $settings
   */
  private function populateFields(&$elements, $account, $settings) {
    if (!is_array($elements)) {
      return;
    }
    $allowed_types = array(
      'email',
      'textfield',
      'select',
      'radios',
      'checkbox',
      'checkboxes',
      'tel',
    );
    foreach ($elements as $key => &$element) {
      if (!empty($element['#type'])) {
        if (in_array($element['#type'], $allowed_types) && !is_numeric($key)) {
          $field = array_search($key, $settings, TRUE);
          if ($field && $account->hasField($field)) {
            $element['#default_value'] = $account->get($field)->value;
          }
        }
        elseif ($element['#type'] == 'fieldset' || $element['#type'] == 'container') {
          $this->populateFields($element, $account, $settings);
        }
      }
    }
  }

  /**
   * Set some values from the profile if there is a mapping
   *
   * @param array $form
   * @param User $account
   */
  public function setDefaultValuesFromAccount(array &$form, User $account) {
    $settings = $this->getUserRegisterSettings();
    if (!empty($settings)) {
      $this->populateFields($form['elements'], $account, $settings);
    }
  }

  /**
   * get register user handler settings if handler is enabled
   *
   * @return array|bool
   */
  private function getUserRegisterSettings(){
    $settings = array();
    $form_settings = $this->getConfiguration();
    if (!empty($form_settings['settings'])) {
      $settings = $form_settings['settings'];
    }
    return $settings;
  }

}
Bạn thấy bài viết này như thế nào?
0 reactions

Add new comment

Image CAPTCHA
Enter the characters shown in the image.
Câu nói tâm đắc: “Điều tuyệt với nhất trong cuộc sống là làm được những việc mà người khác tin là không thể!”

Related Articles

Master list (in progress) of how to get parts of fields for use in Twig templates. I’m always having to look these up, so I thought I’d hash them out and write them down.

Litespeed Cache là plugin WordPress dùng để kết hợp với Web Server LiteSpeed nhằm tăng tốc website WordPress của bạn gấp nhiều lần

In this article, we are going to see how some tools & libraries will make people's lives easier during the development & code review process.

In this tutorial, you will learn how to improve the custom code, theme and module, and general code development by using the pre-commit hook on git

Trước khi tìm hiểu xem PHP Code Sniffer là gì thì các bạn cần phải nắm được coding convention là gì đã.