You are here

function commerce_customer_field_widget_form in Commerce Core 7

Implements hook_field_widget_form().

Used to define the form element for custom widgets.

File

modules/customer/commerce_customer.module, line 979
Defines the customer profile entity and API functions to manage customers and interact with them.

Code

function commerce_customer_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {

  // Define the complex customer profile reference field widget.
  if ($instance['widget']['type'] == 'commerce_customer_profile_manager') {
    $profile_type = commerce_customer_profile_type_load($field['settings']['profile_type']);

    // Do not attempt to render the widget for a non-existent profile type.
    if (empty($profile_type)) {
      drupal_set_message(t('Field %field_name attempted to use the non-existing customer profile type %type.', array(
        '%field_name' => $field['field_name'],
        '%type' => $field['settings']['profile_type'],
      )), 'error');
      return array();
    }

    // Build an array of customer profile IDs from this field's values.
    $profile_ids = array();
    foreach ($items as $item) {
      $profile_ids[] = $item['profile_id'];
    }

    // Load the profiles for temporary storage in the form array.
    $profiles = commerce_customer_profile_load_multiple($profile_ids);
    if (empty($profiles)) {
      if (!empty($form_state['add_profile_' . $profile_type['type']])) {

        // If the "Add profile" button is clicked, create a new profile.
        array_push($profiles, commerce_customer_profile_new($profile_type['type']));
      }
      else {

        // Otherwise add an empty array to make the "Add profile" button show up.
        array_push($profiles, array());
      }
    }

    // Update the base form element array to use the proper validate function.
    $element += array(
      '#element_validate' => array(
        'commerce_customer_profile_manager_validate',
      ),
      'profiles' => array(
        '#tree' => TRUE,
      ),
    );

    // Add a set of elements to the form for each referenced profile.
    $key = 0;
    foreach ($profiles as $profile) {
      $wrapper_id = 'replace_' . $key . '_' . $profile_type['type'];
      $element['profiles'][$key] = array(
        '#type' => 'fieldset',
        '#title' => check_plain($profile_type['name']),
        '#parents' => array_merge($element['#field_parents'], array(
          $element['#field_name'],
          $langcode,
          'profiles',
          $key,
        )),
        '#prefix' => '<div id="' . $wrapper_id . '">',
        '#suffix' => '</div>',
      );
      if (empty($profile)) {

        // There's no profile of this type for this order, show an "add
        // profile" button.
        $element['profiles'][$key]['actions']['add_' . $profile_type['type']] = array(
          '#type' => 'submit',
          '#value' => t('Add @type', array(
            '@type' => strtolower($profile_type['name']),
          )),
          '#submit' => array(
            'commerce_customer_add_profile',
          ),
          '#limit_validation_errors' => array(
            array_merge($element['#field_parents'], array(
              $element['#field_name'],
            )),
          ),
          '#ajax' => array(
            'callback' => 'commerce_customer_add_profile_callback',
            'method' => 'replace',
            'wrapper' => $wrapper_id,
          ),
          '#commerce_customer_profile_type' => $profile_type['type'],
        );
        continue;
      }

      // Store the original customer profile for later comparison.
      $element['profiles'][$key]['profile'] = array(
        '#type' => 'value',
        '#value' => $profile,
      );
      field_attach_form('commerce_customer_profile', $profile, $element['profiles'][$key], $form_state);

      // Tweak the form to remove the fieldset from the address field if there
      // is only one on this profile.
      $addressfields = array();
      foreach (commerce_info_fields('addressfield', 'commerce_customer_profile') as $field_name => $field) {

        // First make sure this addressfield is part of the current profile.
        if (!empty($element['profiles'][$key][$field_name]['#language'])) {
          $langcode = $element['profiles'][$key][$field_name]['#language'];

          // Only consider this addressfield if it's represented on the form.
          if (!empty($element['profiles'][$key][$field_name][$langcode])) {
            $addressfields[] = array(
              $field_name,
              $langcode,
            );
          }
        }
      }

      // Check to ensure only one addressfield was found on the form.
      if (count($addressfields) == 1) {
        list($field_name, $langcode) = array_shift($addressfields);
        foreach (element_children($element['profiles'][$key][$field_name][$langcode]) as $delta) {
          if ($element['profiles'][$key][$field_name][$langcode][$delta]['#type'] != 'submit') {
            $element['profiles'][$key][$field_name][$langcode][$delta]['#type'] = 'container';
          }
        }

        // Remove the default #parents array so the normal tree can do its thing.
        unset($element['profiles'][$key]['#parents']);
      }

      // This checkbox will be overridden with a clickable delete image.
      // TODO: Make this an #ajaxy submit button.
      if ($profile->profile_id) {

        // Create a title for this box based on whether or not the currently
        // referenced customer profile can be deleted.
        if (commerce_customer_profile_can_delete($profile)) {
          $title = t('Delete this profile');
        }
        else {
          $title = t('Clear this profile');
        }
        $element['profiles'][$key]['remove'] = array(
          '#type' => 'checkbox',
          '#title' => $title,
          '#default_value' => FALSE,
          '#access' => commerce_customer_profile_access('delete', $profile),
          '#weight' => 100,
        );
      }
      else {

        // Entity is not saved yet, show a "cancel" button.
        $element['profiles'][$key]['actions']['cancel_' . $profile_type['type']] = array(
          '#type' => 'submit',
          '#value' => t('Cancel'),
          '#submit' => array(
            'commerce_customer_cancel_profile',
          ),
          '#limit_validation_errors' => array(
            array_merge($element['#field_parents'], array(
              $element['#field_name'],
            )),
          ),
          '#ajax' => array(
            'callback' => 'commerce_customer_add_profile_callback',
            'method' => 'replace',
            'wrapper' => $wrapper_id,
          ),
          '#commerce_customer_profile_type' => $profile_type['type'],
        );
      }
      $key += 1;
    }

    // If the reference field is not required, unrequire any elements in the
    // profile edit form.
    if (!$delta == 0 || !$instance['required']) {
      commerce_unrequire_form_elements($element);
    }
    return $element;
  }
}