You are here

function commerce_registration_form_commerce_order_ui_order_form_alter in Commerce Registration 7.2

Implements hook_form_FORM_ID_alter().

Alters the commerce_order_ui_form so registrations can affect the quantity of line items, select how registrations affect the quantity and to add a a section defined by commerce_registration_field_extra_fields() for managing registrations associated with each registration enabled line item.

File

./commerce_registration.module, line 780
Commerce Registration module code.

Code

function commerce_registration_form_commerce_order_ui_order_form_alter(&$form, &$form_state, $form_id) {
  drupal_add_css(drupal_get_path('module', 'commerce_registration') . '/theme/commerce_registration.admin.css');

  // If the user is editing an order, load a fresh copy, but don't mess with the
  // form_state version because other modules like commerce_line_item depend on
  // staged changes they have made to it until it is saved.
  if ($form_state['commerce_order']->order_id) {
    $order = commerce_order_load($form_state['commerce_order']->order_id);
  }
  else {
    $order = $form_state['commerce_order'];
  }
  $line_item_registrations = array();
  $sync = FALSE;
  $submit = FALSE;

  // Build an array of line item IDs from this field's values.
  if (isset($form['commerce_line_items']) && isset($form['commerce_line_items']['#language']) && isset($form['commerce_line_items'][$form['commerce_line_items']['#language']]['line_items'])) {
    $is_odd = TRUE;
    foreach ($form['commerce_line_items'][$form['commerce_line_items']['#language']]['line_items'] as $line_item_id => &$line_item_form) {
      $line_item = commerce_line_item_load($line_item_id);
      if (isset($line_item->commerce_product) && ($line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item))) {
        $product_id = (int) $line_item_wrapper->commerce_product->product_id
          ->value();
        if (commerce_registration_product_has_registration_field($product_id)) {
          $most_recent = $line_item_id;

          // Build a table for each registration enabled line item.
          $prodkey = $line_item_id . 'prod-' . $line_item_wrapper->commerce_product->sku
            ->value();
          $line_item_title = commerce_line_item_title($line_item);
          $title_var_ary = array(
            '%line_item_title' => $line_item_title,
            '@line_item_id' => $line_item_id,
          );
          $odd_even = $is_odd ? 'odd' : 'even';
          $is_odd = !$is_odd;
          $first = !$line_item_registrations;
          $line_item_registrations[$line_item_id] = array(
            '#type' => 'fieldset',
            '#collapsible' => FALSE,
            '#title' => t('Registration information for %line_item_title - Line item #@line_item_id.', $title_var_ary),
            '#element_validate' => array(
              'commerce_registration_line_item_registrations_validate',
            ),
            '#prefix' => '<div id="li-reg-' . $line_item_id . '" class="commerce-registration-line-item-registrations">',
            '#suffix' => '</div>',
            '#attributes' => array(
              'class' => array(
                $odd_even,
              ),
            ),
          );

          // For aesthetics.
          if ($first) {
            $line_item_registrations[$most_recent]['#attributes']['class'][] = 'first';
          }

          // Add a checkbox for toggling the ability to sync line item quantity
          // with the number of registrations.
          $sync = isset($line_item->data['sync_registrations']) ? (bool) $line_item->data['sync_registrations'] : TRUE;
          $line_item_registrations[$line_item_id]['sync_registrations'] = array(
            // Lets explicitly set the id so we know we can set focus back to
            // it after an ajax call.
            '#id' => 'edit-commerce-registration-line-item-registrations-' . $line_item_id . '-sync-registrations',
            '#title' => t('Sync line item quantity'),
            '#description' => t("When checked, the line item associated with this table of registrations' quantity will be kept in sync with the number of people registered. Uncheck this box if you would like to be able to update the quantity manually. For example to put the order back into checkout state and add additional registrations."),
            '#type' => 'checkbox',
            '#default_value' => $sync,
            '#ajax' => array(
              'callback' => 'commerce_registration_line_item_registrations_refresh',
            ),
            '#limit_validation_errors' => array(
              array(
                'commerce_registration',
                'line_item_registrations',
                $line_item_id,
                'sync_registrations',
              ),
            ),
            '#executes_submit_callback' => TRUE,
            '#submit' => array(
              'commerce_registration_line_item_registrations_sync',
            ),
          );

          // Custom theme element for displaying a table of registrations and
          // actions available for each.
          $line_item_registrations[$line_item_id]['registrations'] = array(
            '#title' => t('Registrations for %line_item.', array(
              '%line_item' => $line_item_title,
            )),
            '#theme' => 'commerce_registration_line_item_registrations',
            '#empty' => t('No registrations associated with this line item yet.'),
            // Pass along the info we need for rendering the registrations.
            '#line_item' => $line_item,
            '#prodkey' => $prodkey,
            '#order' => $order,
          );
          if (isset($order->data) && isset($order->data['register_entities'][$prodkey])) {
            foreach ($order->data['register_entities'][$prodkey] as $delta => $registration) {
              $registration_id = $registration->registration_id;

              // Track the delta from the order->data for later processing.
              $line_item_registrations[$line_item_id]['registrations'][$registration_id]['delta'] = array(
                '#type' => 'value',
                '#value' => $delta,
              );

              // Assign a remove button for deleting a specific registration.
              $line_item_registrations[$line_item_id]['registrations'][$registration_id]['registration_remove'] = array(
                '#type' => 'checkbox',
                '#default_value' => FALSE,
                '#limit_validation_errors' => array(
                  array(
                    'commerce_registration',
                    'line_item_registrations',
                    $line_item_id,
                    'registrations',
                    $registration_id,
                    'registration_remove',
                  ),
                ),
                // TODO: AJAXify the remove checkboxes, but it will require an
                // intermidiate confirmation step so users don't accidentally
                // remove registrations. Consider something like the
                // https://github.com/gdkraus/accessible-modal-dialog modal.

                //'#ajax' => array(

                //  'callback' => 'commerce_registration_line_item_registrations_refresh',

                //),
                '#access' => entity_access('delete', 'registration', $registration),
                '#executes_submit_callback' => TRUE,
                '#submit' => array(
                  'commerce_registration_line_item_registration_delete',
                  'commerce_registration_line_item_registrations_sync',
                ),
              );
            }
          }
          $entity_type = 'commerce_product';

          // Build a parents array for this element's values in the form.
          $line_item_registrations[$line_item_id]['registration_control'] = array(
            '#type' => 'fieldset',
            '#tree' => TRUE,
            '#prefix' => '<div id="reg-new-' . $line_item_id . '">',
            '#suffix' => '</div>',
            '#attached' => array(
              'css' => array(),
            ),
            '#attributes' => array(
              'class' => array(
                'commerce-registration-line-item-registrations-controls',
              ),
            ),
          );
          if (registration_status($entity_type, $product_id)) {

            // If the the form has been instructed to add a new registration for
            // this line item...
            if (!empty($form_state['line_item_registration_add']) && isset($form_state['line_item_registration_add'][$line_item_id])) {

              // Get the langcode of the order.
              $parent_langcode = entity_language('commerce_order', $order);
              $registration_form = array(
                '#type' => 'container',
                '#op' => 'add',
                // Used by Field API and controller methods to find the relevant
                // values in $form_state.
                '#parents' => array(
                  'commerce_registration',
                  'line_item_registrations',
                  $line_item_id,
                  'registration_control',
                  'form',
                ),
                '#parent_language' => $parent_langcode,
              );
              $registration_form = registration_form($registration_form, $form_state, $form_state['line_item_registration_add'][$line_item_id]);

              // We may end up with more then one line item that is adding a
              // new registration so save it in a unique form_state location.
              unset($form_state['registration']);

              // Hijack the submit and cancel elements from the registration
              // form.
              unset($registration_form['actions']);

              // Add the actions.
              $registration_form['actions'] = array(
                '#type' => 'container',
                '#weight' => 100,
              );
              $registration_form['actions']['registration_control_submit'] = array(
                '#type' => 'submit',
                '#value' => t('Save registraton'),
                '#name' => 'reg-add-submit-' . $line_item_id,
                '#limit_validation_errors' => array(
                  $registration_form['#parents'],
                ),
                '#ajax' => array(
                  'callback' => 'commerce_registration_line_item_registrations_refresh',
                ),
                '#submit' => array(
                  'commerce_registration_line_item_control_save',
                  'commerce_registration_line_item_control_reset',
                  'commerce_registration_line_item_registrations_sync',
                ),
              );
              $registration_form['actions']['registration_control_cancel'] = array(
                '#type' => 'submit',
                '#value' => t('Cancel'),
                '#name' => 'reg-add-cancel-' . $line_item_id,
                '#limit_validation_errors' => array(),
                '#ajax' => array(
                  'callback' => 'commerce_registration_line_item_registrations_refresh',
                ),
                '#submit' => array(
                  'commerce_registration_line_item_control_reset',
                ),
              );
              $line_item_registrations[$line_item_id]['registration_control']['form'] = $registration_form;

              // Flag submit so that we remember to add our submit callbacks
              // to the order as well.
              $submit = TRUE;
            }
            else {

              // Add a button for adding a new registration.
              $line_item_registrations[$line_item_id]['registration_control']['registration_control_add'] = array(
                '#type' => 'submit',
                '#value' => t('Add a registration'),
                '#name' => 'reg-add-' . $line_item_id,
                '#ajax' => array(
                  'callback' => 'commerce_registration_line_item_registrations_refresh',
                ),
                '#limit_validation_errors' => array(),
                '#submit' => array(),
              );
            }
          }
          else {
            $line_item_registrations[$line_item_id]['registration_control']['not_open'] = array(
              '#markup' => '<p>' . t('It is not possible to add registrations at this time. Check the registration settings and spaces available for this product.') . '</p>',
            );
          }

          // Make some alterations to the line items table for line items that
          // contain products that are commerce_registration enabled. Includes
          // some accessibility features to link the line item quantity with
          // its associated registrations.
          $line_item_form['quantity']['#suffix'] = '<div><span id="qty-desc-' . $line_item_id . '"><a href="#line-item-reg-' . $line_item_id . '" class="element-invisible element-focusable">' . t('Click here to manage the registrations associated with this line item instead of changing the quantity directly.') . '</a></span></div>';
          $line_item_form['quantity']['#attributes']['aria-describedby'] = 'qty-desc-' . $line_item_id;

          // Keep the line item quantity in sync with the registrations by
          // making the quantity read only.
          if (isset($order->data) && !empty($order->data['register_entities'][$prodkey]) && $line_item->quantity && $sync) {
            $line_item_form['quantity']['#attributes']['readonly'] = '';
          }
        }
      }
    }
  }
  if ($line_item_registrations) {

    // For aesthetics.
    if ($most_recent) {
      $line_item_registrations[$most_recent]['#attributes']['class'][] = 'last';
    }
    $form['commerce_registration'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#title' => t('Registrations'),
      '#collapsed' => FALSE,
      '#tree' => TRUE,
      '#prefix' => '<div id="commerce-line-item_registrations"><div aria-live="assertive"><div id="commerce-registration-messages"></div></div>',
      '#suffix' => '</div>',
      'line_item_registrations' => $line_item_registrations,
    );
  }

  // Add submit handlers to the order form as well in case the form is submitted
  // in a way other then by clicking our 'Submit registration' button.
  $submit_callbacks = array(
    'commerce_registration_line_item_registration_delete',
    'commerce_registration_line_item_control_save',
    'commerce_registration_line_item_control_reset',
    'commerce_registration_line_item_registrations_sync',
  );
  $form['#submit'] = array_merge($form['#submit'], $submit_callbacks);
  $form['actions']['submit']['#submit'] = array_merge($form['actions']['submit']['#submit'], $submit_callbacks);
}