eca-1.0.x-dev/modules/form/src/Hook/FormHooks.php

modules/form/src/Hook/FormHooks.php
<?php

namespace Drupal\eca_form\Hook;

use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Hook\Order\Order;
use Drupal\Core\Render\Element;
use Drupal\eca\Event\TriggerEvent;

/**
 * Implements form hooks for the ECA Form submodule.
 */
class FormHooks {

  /**
   * Constructs a new FormHooks object.
   */
  public function __construct(
    protected TriggerEvent $triggerEvent,
  ) {}

  /**
   * Implements hook_form_alter().
   */
  #[Hook('form_alter', order: Order::Last)]
  public function formAlter(array &$form, FormStateInterface $form_state): void {
    if (isset($form['#form_id']) && ($form['#form_id'] === 'system_modules_uninstall_confirm_form')) {
      // When this module is being uninstalled via UI, it will lead to a fatal.
      // To avoid this, the module uninstall confirm form is not supported.
      // @see https://www.drupal.org/project/eca/issues/3305797
      return;
    }
    if ($form_state->has('skip_eca')) {
      // When flagged by a component to skip ECA, then skip it.
      return;
    }
    $this->triggerEvent->dispatchFromPlugin('form:form_build', $form, $form_state);
    // Add the handlers on class-level, to avoid expensive and possibly faulty
    // serialization of nested object references during form submissions.
    $form['#process'][] = [static::class, 'process'];
    $form['#after_build'][] = [static::class, 'afterBuild'];
    $form['#validate'][] = [static::class, 'validate'];
    $form['#submit'][] = [static::class, 'submit'];
    $this->addSubmitHandler($form);
  }

  /**
   * Implements hook_inline_entity_form_entity_form_alter().
   */
  #[Hook('inline_entity_form_entity_form_alter')]
  public function inlineEntityFormEntityFormAlter(array &$entity_form, FormStateInterface $form_state): void {
    if ($form_state->has('skip_eca')) {
      // When flagged by a component to skip ECA, then skip it.
      return;
    }
    if (!isset($entity_form['#eca_ief_info'])) {
      return;
    }
    $info = &$entity_form['#eca_ief_info'];
    $this->triggerEvent->dispatchFromPlugin('form:ief_build', $entity_form, $form_state, $entity_form['#entity'], $info['parent'], $info['field_name'], $info['delta'], $info['widget_plugin_id']);
    // Pass along the info to the after build callback, but only parent UUID
    // is needed there.
    $info['parent'] = $info['parent']->uuid();
  }

  /**
   * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
   *
   * For the "inline_entity_form_complex" widget plugin ID.
   */
  #[Hook('field_widget_single_element_inline_entity_form_complex_form_alter')]
  public function fieldWidgetSingleElementInlineEntityFormComplexFormAlter(array &$element, FormStateInterface $form_state, array &$context): void {
    if ($form_state->has('skip_eca')) {
      // When flagged by a component to skip ECA, then skip it.
      return;
    }

    $delta = $context['delta'] ?? NULL;
    if (isset($element['#ief_id']) && ($triggering_element = &$form_state->getTriggeringElement())) {
      if (isset($triggering_element['#ief_row_delta'])) {
        $delta = $triggering_element['#ief_row_delta'];
      }
      else {
        $entities = $form_state->get([
          'inline_entity_form',
          $element['#ief_id'],
          'entities',
        ]);
        if (!empty($entities)) {
          $delta = count($entities);
        }
        elseif (isset($triggering_element['#ief_form']) && $triggering_element['#ief_form'] === 'add') {
          $delta = $context['items']->count();
        }
      }
    }
    if (!isset($delta)) {
      return;
    }

    // Pass along information for ::alterInlineEntityForm().
    if (isset($element['inline_entity_form'])) {
      $entity_form = &$element['inline_entity_form'];
    }
    elseif (isset($element['entities'][$delta]['form']['inline_entity_form'])) {
      $entity_form = &$element['entities'][$delta]['form']['inline_entity_form'];
    }
    elseif (isset($element['form']['inline_entity_form'])) {
      $entity_form = &$element['form']['inline_entity_form'];
    }
    else {
      return;
    }
    $info = [
      'parent' => $context['items']->getEntity(),
      'field_name' => $context['items']->getFieldDefinition()->getName(),
      'delta' => $delta,
      'widget_plugin_id' => $context['widget']->getPluginId(),
    ];
    $entity_form['#eca_ief_info'] = &$info;
  }

  /**
   * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
   *
   * For the "inline_entity_form_simple" widget plugin ID.
   */
  #[Hook('field_widget_single_element_inline_entity_form_simple_form_alter')]
  public function fieldWidgetSingleElementInlineEntityFormSimpleFormAlter(array &$element, FormStateInterface $form_state, array &$context): void {
    $this->fieldWidgetSingleElementInlineEntityFormComplexFormAlter($element, $form_state, $context);
  }

  /**
   * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
   *
   * For the "paragraphs" widget plugin ID.
   */
  #[Hook('field_widget_single_element_paragraphs_form_alter')]
  public function fieldWidgetSingleElementParagraphsFormAlter(array &$element, FormStateInterface $form_state, array &$context): void {
    if ($form_state->has('skip_eca')) {
      // When flagged by a component to skip ECA, then skip it.
      return;
    }

    // Skip if subform is null or not an array
    // to prevent InlineEntityFormBuild errors.
    if (!isset($element['subform']) || !is_array($element['subform'])) {
      return;
    }

    $field_name = $context['items']->getFieldDefinition()->getName();
    $delta = $context['delta'];
    $widget_state = WidgetBase::getWidgetState($element['#field_parents'], $field_name, $form_state);
    /** @var \Drupal\paragraphs\ParagraphInterface $paragraph */
    $paragraph = $widget_state['paragraphs'][$delta]['entity'] ?? $context['items']->get($delta)->entity;
    $parent = $context['items']->getEntity();
    $widget_plugin_id = $context['widget']->getPluginId();

    $this->triggerEvent->dispatchFromPlugin('form:ief_build', $element['subform'], $form_state, $paragraph, $parent, $field_name, $delta, $widget_plugin_id);
  }

  /**
   * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
   *
   * For the "entity_reference_paragraphs" widget plugin ID.
   */
  #[Hook('field_widget_single_element_entity_reference_paragraphs_form_alter')]
  public function fieldWidgetSingleElementEntityReferenceParagraphsFormAlter(array &$element, FormStateInterface $form_state, array &$context): void {
    $this->fieldWidgetSingleElementParagraphsFormAlter($element, $form_state, $context);
  }

  /**
   * Add submit handler to nested elements if necessary.
   *
   * Walks through the element array recursively and adds the extra
   * submit-handler to all elements where necessary.
   *
   * @param array $elements
   *   A render array to walk through.
   */
  protected function addSubmitHandler(array &$elements): void {
    foreach (Element::children($elements) as $key) {
      if (is_array($elements[$key])) {
        // Only add our submit handler, when at least one other submit handler
        // is present for the element. The form submitter service calls
        // form-level submit handlers when no submit handler is specified, i.e.
        // either no #submit array is given at all, or the given array is empty.
        // @see \Drupal\Core\Form\FormSubmitter::executeSubmitHandlers()
        if (!empty($elements[$key]['#submit'])) {
          $submit_handler = [static::class, 'submit'];
          // Make sure our submit handler is added only once.
          if (!in_array($submit_handler, $elements[$key]['#submit'], TRUE)) {
            $elements[$key]['#submit'][] = $submit_handler;
          }
        }
        $this->addSubmitHandler($elements[$key]);
      }
    }
  }

  /**
   * Gets the trigger event service.
   *
   * @return \Drupal\eca\Event\TriggerEvent
   *   The trigger event service.
   */
  public static function triggerEvent(): TriggerEvent {
    return \Drupal::service('eca.trigger_event');
  }

  /**
   * Triggers the event to process a form.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The form array.
   */
  public static function process(array $form, FormStateInterface $form_state): array {
    if (!$form_state->has('skip_eca')) {
      static::triggerEvent()->dispatchFromPlugin('form:form_process', $form, $form_state);
    }
    return $form;
  }

  /**
   * Triggers the event after form building was completed.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The form array.
   */
  public static function afterBuild(array $form, FormStateInterface $form_state): array {
    if (!$form_state->has('skip_eca')) {
      static::triggerEvent()->dispatchFromPlugin('form:form_after_build', $form, $form_state);
    }
    return $form;
  }

  /**
   * Triggers the event to validate a form.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public static function validate(array $form, FormStateInterface $form_state): void {
    if (!$form_state->has('skip_eca')) {
      static::triggerEvent()->dispatchFromPlugin('form:form_validate', $form, $form_state);
    }
  }

  /**
   * Triggers the event to submit a form.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public static function submit(array $form, FormStateInterface $form_state): void {
    if (!$form_state->has('skip_eca')) {
      static::triggerEvent()->dispatchFromPlugin('form:form_submit', $form, $form_state);
    }
  }

}

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

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