You are here

function business_rules_field_widget_form_alter in Business Rules 2.x

Same name and namespace in other branches
  1. 8 business_rules.module \business_rules_field_widget_form_alter()

Implements hook_field_widget_form_alter().

File

./business_rules.module, line 189
Business Rules module.

Code

function business_rules_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {

  // @todo check patch inline_entity_form_2973571_1.patch.
  $form_object = $form_state
    ->getFormObject();

  // Establish whether we're in a normal EntityForm context or an inline
  // QuickeditFieldForm context and retrieve the entity from the respectively
  // appropriate place.
  if (isset($context['items']) && $context['items'] instanceof EntityReferenceFieldItemListInterface) {

    /**
     * @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items
     */
    $items = $context['items'];
    $entity = $items
      ->getEntity();
  }
  elseif ($form_object instanceof EntityFormInterface) {
    $entity = $form_object
      ->getEntity();
  }
  else {
    if ($form_object instanceof QuickEditFieldForm) {
      $entity = $form_state
        ->getBuildInfo()['args'][0];
    }
    else {
      $entity = new stdClass();
    }
  }
  if ($entity instanceof EntityInterface) {

    // Check if the field is a dependent field.

    /** @var \Drupal\Core\Field\FieldItemList $items */
    $items = $context['items'];
    $current_field = $items
      ->getFieldDefinition()
      ->getName();

    // Check if field is configured as parent of one dependent field.
    if (method_exists($entity, 'getFieldDefinitions')) {
      $fields_definitions = $entity
        ->getFieldDefinitions();
      $parent_field = NULL;

      // Check if current field has children.
      $child_fields = [];
      foreach ($fields_definitions as $field_name => $field_definition) {
        $handler = $field_definition
          ->getSetting('handler');
        if ($handler == 'business_rules_views') {
          $handle_settings = $field_definition
            ->getSetting('handler_settings');
          $parent_field = $handle_settings['business_rules_view']['parent_field'];
          $has_children = $parent_field == $current_field;
          if ($has_children) {
            $child_fields[] = $field_name;
          }
        }
      }

      // Add ajax to parent field.
      if (count($child_fields)) {
        $children = isset($element['#ajax']['br_children']) ? $element['#ajax']['br_children'] : [];
        $children += $child_fields;
        $ajax_definition = [
          'callback' => '\\Drupal\\business_rules\\Plugin\\EntityReferenceSelection\\BusinessRulesViewsSelection::updateDependentField',
          'event' => 'change',
          'progress' => [
            'type' => 'throbber',
          ],
          'br_children' => $children,
        ];
        if (!empty($context['widget']) && $context['widget'] instanceof EntityReferenceAutocompleteWidget && !empty($element['target_id'])) {
          $ajax_definition['event'] = 'autocompleteclose';
          $element['target_id']['#ajax'] = $ajax_definition;
        }
        else {
          $element['#ajax'] = $ajax_definition;
        }
        $element['#attached']['library'][] = 'business_rules/dependentField';
      }
    }

    // Prepare the event to FormFieldAlter.
    $reacts_on_definition = \Drupal::getContainer()
      ->get('plugin.manager.business_rules.reacts_on')
      ->getDefinition('form_field_alter');

    // Business rules processor needs to process this event every time it's
    // called by Drupal. There is no necessity of loop control here. In this
    // case we are creating an uuid because there is no risk of infinite loop.
    $loop_control = \Drupal::getContainer()
      ->get('uuid')
      ->generate();
    $event = new BusinessRulesEvent($element, [
      'form_state' => $form_state,
      'element' => $element,
      'context' => $context,
      'entity_type_id' => $entity
        ->getEntityTypeId(),
      'bundle' => $entity
        ->bundle(),
      'entity' => $entity,
      'entity_unchanged' => property_exists($entity, 'original') ? $entity->original : $entity,
      'reacts_on' => $reacts_on_definition,
      'loop_control' => $loop_control,
    ]);

    /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
    $event_dispatcher = \Drupal::service('event_dispatcher');
    $event_dispatcher
      ->dispatch($reacts_on_definition['eventName'], $event);

    // Now we need to replace the current element by the changed one.
    $element = $event
      ->getArgument('element');
  }
}