You are here

public function CustomerProfile::buildInlineForm in Commerce Core 8.2

Builds the inline form.

Parameters

array $inline_form: The inline form, containing the following basic properties:

  • #parents: Identifies the location of the field values in $form_state.

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

Return value

array The built inline form.

Overrides InlineFormBase::buildInlineForm

File

modules/order/src/Plugin/Commerce/InlineForm/CustomerProfile.php, line 155

Class

CustomerProfile
Provides an inline form for managing a customer profile.

Namespace

Drupal\commerce_order\Plugin\Commerce\InlineForm

Code

public function buildInlineForm(array $inline_form, FormStateInterface $form_state) {
  $inline_form = parent::buildInlineForm($inline_form, $form_state);

  // Allows a widget to vary when used for billing versus shipping purposes.
  // Available in hook_field_widget_form_alter() via $context['form'].
  $inline_form['#profile_scope'] = $this->configuration['profile_scope'];
  assert($this->entity instanceof ProfileInterface);
  $profile_type_id = $this->entity
    ->bundle();
  $allows_multiple = $this->addressBook
    ->allowsMultiple($profile_type_id);
  $customer = $this
    ->loadUser($this->configuration['address_book_uid']);
  $available_countries = $this->configuration['available_countries'];
  $address_book_profile = NULL;
  if ($customer
    ->isAuthenticated() && $allows_multiple) {

    // Multiple address book profiles are allowed, prepare the dropdown.
    $address_book_profiles = $this->addressBook
      ->loadAll($customer, $profile_type_id, $available_countries);
    if ($address_book_profiles) {
      $user_input = (array) NestedArray::getValue($form_state
        ->getUserInput(), $inline_form['#parents']);
      if (!empty($user_input['select_address'])) {

        // An option was selected, pre-fill the profile form.
        $address_book_profile = $this
          ->getProfileForOption($user_input['select_address']);
      }
      elseif ($this->entity
        ->isNew()) {

        // The customer profile form is being rendered for the first time.
        // Use the default profile to pre-fill the profile form.
        $address_book_profile = $this
          ->selectDefaultProfile($address_book_profiles);
      }
    }
    $profile_options = $this
      ->buildOptions($address_book_profiles);
    if ($address_book_profile) {
      $selected_option = $this
        ->selectOptionForProfile($address_book_profile);
    }
    else {
      $selected_option = $this->entity
        ->isNew() ? '_new' : '_original';

      // Select the address book profile, if the _original option was removed.
      if ($selected_option == '_original' && !isset($profile_options['_original'])) {
        $selected_option = $this->entity
          ->getData('address_book_profile_id');
      }
    }
    $inline_form['#after_build'][] = [
      get_called_class(),
      'clearValues',
    ];
    $inline_form['select_address'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Select an address'),
      '#options' => $profile_options,
      '#default_value' => $selected_option,
      '#access' => !empty($address_book_profiles),
      '#ajax' => [
        'callback' => [
          get_called_class(),
          'ajaxRefresh',
        ],
        'wrapper' => $inline_form['#id'],
      ],
      '#attributes' => [
        'class' => [
          'available-profiles',
        ],
      ],
      '#weight' => -999,
    ];
  }
  elseif ($customer
    ->isAuthenticated() && $this->entity
    ->isNew()) {

    // A single address book profile is allowed.
    // The customer profile form is being rendered for the first time.
    // Use the default profile to pre-fill the profile form.
    $address_book_profile = $this->addressBook
      ->load($customer, $profile_type_id, $available_countries);
  }

  // Copy field values from the address book profile to the actual profile.
  if ($address_book_profile) {
    $this->entity
      ->populateFromProfile($address_book_profile);
    $this->entity
      ->unsetData('copy_to_address_book');
    $this->entity
      ->unsetData('address_book_profile_id');
    if (!$address_book_profile
      ->isNew()) {
      $this->entity
        ->setData('address_book_profile_id', $address_book_profile
        ->id());
    }
  }
  if ($this
    ->shouldRender($inline_form, $form_state)) {
    $view_builder = $this->entityTypeManager
      ->getViewBuilder('profile');
    $inline_form['rendered'] = $view_builder
      ->view($this->entity);
    $inline_form['edit_button'] = [
      '#type' => 'button',
      '#name' => $inline_form['#profile_scope'] . '_edit',
      '#value' => $this
        ->t('Edit'),
      '#ajax' => [
        'callback' => [
          get_called_class(),
          'ajaxRefresh',
        ],
        'wrapper' => $inline_form['#id'],
      ],
      '#limit_validation_errors' => [
        $inline_form['#parents'],
      ],
      '#attributes' => [
        'class' => [
          'address-book-edit-button',
        ],
      ],
    ];
  }
  else {

    // The $address_book_profile_id will be missing if the source
    // address book profile was deleted, or has never existed.
    $address_book_profile_id = $this->entity
      ->getData('address_book_profile_id');
    $profile_storage = $this->entityTypeManager
      ->getStorage('profile');
    if ($address_book_profile_id && !$profile_storage
      ->load($address_book_profile_id)) {
      $this->entity
        ->unsetData('address_book_profile_id');
    }
    $form_display = $this
      ->loadFormDisplay();
    $form_display
      ->buildForm($this->entity, $inline_form, $form_state);
    $inline_form = $this
      ->prepareProfileForm($inline_form, $form_state);
    $edit = $address_book_profile ? !$address_book_profile
      ->isNew() : !$this->entity
      ->isNew();
    $update_on_copy = (bool) $this->entity
      ->getData('address_book_profile_id');
    if ($allows_multiple) {

      // The copy checkbox is:
      // - Shown and checked for customers adding a new address.
      // - Shown and unchecked for admins adding a new address.
      // - Hidden and checked for customers and admins editing an address
      //   book profile which is still in sync with the current profile.
      // - Hidden and unchecked if the address book profile is no longer in
      //   sync (determined and done via the logic in buildOptions().
      $default_value = TRUE;
      if ($this->configuration['admin'] && !$edit) {
        $default_value = FALSE;
      }
      if ($edit && !$update_on_copy) {

        // The profile was originally not copied to the address book,
        // preserve that decision.
        $default_value = FALSE;
      }
      $visible = !$default_value || !$update_on_copy;
    }
    else {

      // The copy checkbox is:
      // - Hidden and checked for customers, since the address book is always
      //   supposed to reflect customer's last entered address.
      // - Shown and unchecked for admins, who need to opt-in to copying.
      $default_value = !$this->configuration['admin'];
      $visible = $this->configuration['admin'];
    }
    $inline_form['copy_to_address_book'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->getCopyLabel($profile_type_id, $update_on_copy),
      '#default_value' => (bool) $this->entity
        ->getData('copy_to_address_book', $default_value),
      '#weight' => 999,
      // Anonymous customers don't have an address book until they register
      // or log in, so the checkbox is not shown to them, to avoid confusion.
      '#access' => $customer
        ->isAuthenticated() && $visible,
    ];
  }
  return $inline_form;
}