simple_multistep-8.x-1.x-dev/simple_multistep.module

simple_multistep.module
<?php

/**
 * @file
 * Contains simple_multistep.module.
 */

use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field_group\FormatterHelper;
use Drupal\simple_multistep\MultistepController;
use Drupal\simple_multistep\MultistepControllerInterface;

/**
 * Implements hook_module_implements_alter().
 */
function simple_multistep_module_implements_alter(&$implementations, $hook) {
  // Perform form_alter after field_group.
  if ($hook === 'form_alter') {
    $group = $implementations['simple_multistep'];
    unset($implementations['simple_multistep']);
    $implementations['simple_multistep'] = $group;
  }
}

/**
 * Implements hook_form_alter().
 */
function simple_multistep_form_alter(array &$form, FormStateInterface $form_state) {
  // Check if form using form group multistep field.
  if (_check_form_multistep($form)) {
    /** @var \Drupal\simple_multistep\MultistepController $multiStep */
    if ($multiStep = $form_state->get('multistep_controller')) {
      $multiStep->updateStepInfo();
    }
    else {
      simple_multistep_register_controller($form, $form_state);
      $multiStep = new $form['#multistep_controller']($form, $form_state);
    }

    $multiStep->setFormState($form_state);
    $multiStep->rebuildForm($form);

    $form_state->set('multistep_controller', $multiStep);

    // Attach style library.
    $form['#attached']['library'][] = 'simple_multistep/simple_multistep';
  }
}

/**
 * Register custom controller from modules.
 */
function simple_multistep_register_controller(array &$form, FormStateInterface $form_state): void {
  // Set default controller.
  $form['#multistep_controller'] = MultistepController::class;
  // Alter the controller from hook.
  \Drupal::moduleHandler()->alter('simple_multistep_controller', $form, $form_state);
  // Set custom controller form others modules.
  $class_controller = $form['#multistep_controller'];
  // Set main and required parent class.
  $controller_interface = MultistepControllerInterface::class;
  if (!is_subclass_of($class_controller, $controller_interface)) {
    throw new \RuntimeException("$class_controller must implements $controller_interface");
  }
}

/**
 * Submit handler for next button.
 */
function simple_multistep_register_next_step(array &$form, FormStateInterface $form_state) {
  /** @var \Drupal\simple_multistep\MultistepController $multiStep */
  $multiStep = $form_state->get('multistep_controller');

  $entity_form = $form_state->getFormObject();
  if ($entity_form instanceof EntityFormInterface) {
    $entity_updated = $entity_form->buildEntity($form, $form_state);
    $entity_form->setEntity($entity_updated);
  }

  $multiStep->increaseStep();
  $form_state->set('multistep_controller', $multiStep);
  $form_state->setRebuild();
}

/**
 * Adjusts the Back button's validation behavior in a multistep form.
 *
 * When the Back button is pressed, this method copies
 * the #limit_validation_errors from the Next button, so that
 * only the fields that would normally be validated are considered.
 * This allows skipping validation for empty fields while still
 * preserving their submitted values in $form_state.
 *
 * Unlike setting '#limit_validation_errors' to an empty array, this approach
 * ensures that field values are not removed from the form state.
 */
function simple_multistep_register_back_validation(array &$form, FormStateInterface $form_state) {
  $trigger = $form_state->getTriggeringElement();

  if ($trigger['#parents'] !== ['back_button'] || empty($form['actions']['next'])) {
    return;
  }

  // Copy Next button's limit_validation_errors to Back button.
  $trigger['#limit_validation_errors'] = $form['actions']['next']['#limit_validation_errors'];

  $form_state->setTriggeringElement($trigger);
}

/**
 * Submit handler for back button.
 */
function simple_multistep_register_back(array &$form, FormStateInterface $form_state) {
  /** @var \Drupal\simple_multistep\MultistepController $multiStep */
  $multiStep = $form_state->get('multistep_controller');

  $entity_form = $form_state->getFormObject();
  if ($entity_form instanceof EntityFormInterface) {
    $entity_updated = $entity_form->buildEntity($form, $form_state);
    $entity_form->setEntity($entity_updated);
  }

  // If current_step more than 0.
  if ($multiStep->getCurrentStep()) {
    $multiStep->reduceStep();
    $form_state->set('multistep_controller', $multiStep);
    $form_state->setRebuild();
  }
}

/**
 * Check if valid multi step form.
 *
 * @param array $form
 *   Form array.
 *
 * @return bool
 *   TRUE if form multi step.
 */
function _check_form_multistep(array $form): bool {
  if (empty($form['#fieldgroups'])) {
    return FALSE;
  }

  foreach ($form['#fieldgroups'] as $fieldgroup) {
    if (is_object($fieldgroup) && $fieldgroup->format_type === 'form_step') {
      return TRUE;
    }
  }

  return FALSE;
}

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 */
function simple_multistep_inline_entity_form_entity_form_alter(array &$entity_form, FormStateInterface $form_state) {

  // Attach the fieldgroups to current entity form.
  $context = [
    'entity_type' => $entity_form['#entity']->getEntityTypeId(),
    'bundle' => $entity_form['#entity']->bundle(),
    'entity' => $entity_form['#entity'],
    'display_context' => 'form',
    'mode' => $entity_form['#form_mode'] ?? 'default',
  ];

  field_group_attach_groups($entity_form, $context);
  FormatterHelper::formProcess($entity_form, $form_state);

  simple_multistep_form_alter($entity_form, $form_state);
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc