You are here

public function ProfileFieldCopy::alterForm in Commerce Shipping 8.2

Alters the inline form.

Adds the field copy checkbox ("Billing same as shipping'). Ensures that field values are copied on submit.

Parameters

array $inline_form: The inline form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Overrides ProfileFieldCopyInterface::alterForm

File

src/ProfileFieldCopy.php, line 72

Class

ProfileFieldCopy
Default implementation of profile field copying ("Billing same as shipping").

Namespace

Drupal\commerce_shipping

Code

public function alterForm(array &$inline_form, FormStateInterface $form_state) {
  $shipping_profile = static::getShippingProfile($form_state);
  if (!$shipping_profile) {

    // No source information is available.
    return;
  }
  $billing_profile = static::getBillingProfile($inline_form);
  $shipping_form_display = static::getFormDisplay($shipping_profile, 'shipping');
  $shipping_fields = array_keys($shipping_form_display
    ->getComponents());
  $user_input = (array) NestedArray::getValue($form_state
    ->getUserInput(), $inline_form['#parents']);

  // Copying is enabled by default for new billing profiles.
  $enabled = $billing_profile
    ->getData('copy_fields', $billing_profile
    ->isNew());
  if ($user_input) {
    if (isset($user_input['copy_fields'])) {
      $enabled = (bool) $user_input['copy_fields']['enable'];
    }
    elseif (isset($user_input['select_address'])) {
      $enabled = FALSE;
    }
  }
  $inline_form['copy_fields'] = [
    '#parents' => array_merge($inline_form['#parents'], [
      'copy_fields',
    ]),
    '#type' => 'container',
    '#weight' => -1000,
    '#shipping_fields' => $shipping_fields,
    '#has_form' => FALSE,
  ];
  $inline_form['copy_fields']['enable'] = [
    '#type' => 'checkbox',
    '#title' => $this
      ->getCopyLabel($inline_form),
    '#default_value' => $enabled,
    '#ajax' => [
      'callback' => [
        get_class($this),
        'ajaxRefresh',
      ],
      'wrapper' => $inline_form['#id'],
    ],
  ];
  if ($enabled) {

    // Copy over the current shipping field values, allowing widgets such as
    // TaxNumberDefaultWidget to rely on them. These values might change
    // during submit, so the profile is populated again in submitForm().
    $billing_profile
      ->populateFromProfile($shipping_profile, $shipping_fields);

    // Disable address book copying and remove all existing fields.
    $inline_form['copy_to_address_book'] = [
      '#type' => 'value',
      '#value' => FALSE,
    ];
    foreach (Element::getVisibleChildren($inline_form) as $key) {
      if (!in_array($key, [
        'copy_fields',
        'copy_to_address_book',
      ])) {
        $inline_form[$key]['#access'] = FALSE;
      }
    }

    // Add field widgets for any non-copied billing fields.
    $form_display = static::getFormDisplay($billing_profile, 'billing', $shipping_fields);
    $billing_fields = array_keys($form_display
      ->getComponents());
    if ($billing_fields) {
      $form_display
        ->buildForm($billing_profile, $inline_form['copy_fields'], $form_state);
      $inline_form['copy_fields']['#has_form'] = TRUE;
    }

    // Replace the existing validate/submit handlers with custom ones.
    foreach ($inline_form['#element_validate'] as &$validate_handler) {
      if ($validate_handler[1] == 'runValidate') {
        $validate_handler = [
          get_class($this),
          'validateForm',
        ];
        break;
      }
    }
    foreach ($inline_form['#commerce_element_submit'] as &$submit_handler) {
      if ($submit_handler[1] == 'runSubmit') {
        $submit_handler = [
          get_class($this),
          'submitForm',
        ];
        break;
      }
    }
  }
  else {
    $billing_profile
      ->unsetData('copy_fields');
  }
}