You are here

function commerce_line_item_manager_validate in Commerce Core 7

Validation callback for a commerce_line_item_manager element.

When the form is submitted, the line item reference field stores the line item IDs as derived from the $element['line_items'] array and updates any referenced line items based on the extra form elements.

1 string reference to 'commerce_line_item_manager_validate'
commerce_line_item_field_widget_form in modules/line_item/commerce_line_item.module
Implements hook_field_widget_form().

File

modules/line_item/commerce_line_item.module, line 1215
Defines the core Commerce line item entity and API functions interact with line items on orders.

Code

function commerce_line_item_manager_validate($element, &$form_state, $form) {
  $value = array();

  // Loop through the line items in the manager table.
  foreach (element_children($element['line_items']) as $line_item_id) {

    // If the line item has been marked for deletion...
    if ($element['line_items'][$line_item_id]['remove']['#value']) {

      // Delete the line item now and don't include it from the $value array.
      commerce_line_item_delete($line_item_id);
    }
    else {

      // Add the line item ID to the current value of the reference field.
      $value[] = array(
        'line_item_id' => $line_item_id,
      );

      // Update the line item based on the values in the additional elements.
      $line_item = clone $element['line_items'][$line_item_id]['line_item']['#value'];

      // Validate the quantity of each line item.
      $element_name = implode('][', $element['line_items'][$line_item_id]['quantity']['#parents']);
      $quantity = $element['line_items'][$line_item_id]['quantity']['#value'];
      if (!is_numeric($quantity) || $quantity <= 0) {
        form_set_error($element_name, t('You must specify a positive number for the quantity'));
      }
      elseif ($element['line_items'][$line_item_id]['quantity']['#datatype'] == 'integer' && (int) $quantity != $quantity) {
        form_set_error($element_name, t('You must specify a whole number for the quantity.'));
      }
      else {
        $line_item->quantity = $quantity;
      }

      // Manually validate the unit price of each line item.
      $unit_price = $form_state['values'][$element['#field_name']][$element['#language']]['line_items'][$line_item_id]['commerce_unit_price'];
      $amount = $unit_price[$element['#language']][0]['amount'];
      $currency_code = $unit_price[$element['#language']][0]['currency_code'];

      // Display an error message for a non-numeric unit price.
      if (!is_numeric($amount)) {
        $name = implode('][', array_merge($element['line_items'][$line_item_id]['commerce_unit_price']['#parents'], array(
          $element['#language'],
          0,
          'amount',
        )));
        form_set_error($name, 'You must enter a numeric value for the unit price.');
      }
      elseif ($amount != $line_item->commerce_unit_price[$element['#language']][0]['amount'] || $currency_code != $line_item->commerce_unit_price[$element['#language']][0]['currency_code']) {

        // Otherwise update the unit price amount if it has changed.
        $line_item->commerce_unit_price = $unit_price;

        // Rebuild the price components array.
        commerce_line_item_rebase_unit_price($line_item);
      }

      // Only save if no errors and values were actually changed.
      if (!form_get_errors() && $line_item != $element['line_items'][$line_item_id]['line_item']['#value']) {
        commerce_line_item_save($line_item);
      }
    }
  }

  // If the "Add line item" button was clicked, store the line item type in the
  // $form_state for the rebuild of the $form array.
  if (!empty($form_state['triggering_element'])) {
    if ($form_state['triggering_element']['#value'] === t('Add line item')) {
      $form_state['line_item_add'] = $element['actions']['line_item_type']['#value'];
      $form_state['rebuild'] = TRUE;
    }
    else {
      unset($form_state['line_item_add']);
      $parent = end($form_state['triggering_element']['#parents']);

      // If the save button was clicked from the line item type action form...
      if ($parent == 'save_line_item') {
        $line_item_type = $element['actions']['line_item_type']['#value'];

        // Extract an order ID from the form if present.
        $order_id = 0;
        if (!empty($form_state['commerce_order'])) {
          $order_id = $form_state['commerce_order']->order_id;
        }

        // Create the new line item.
        $line_item = commerce_line_item_new($line_item_type['type'], $order_id);

        // If this type specifies a valid add form callback function...
        if ($callback = commerce_line_item_type_callback($line_item_type, 'add_form_submit')) {

          // Allow the callback to alter data onto the line item to be saved and
          // to return an error message if something goes wrong.
          $error = $callback($line_item, $element, $form_state, $form);
        }
        else {

          // Assume no error if the callback isn't specified.
          $error = FALSE;
        }

        // If we didn't end up with any errors...
        if (empty($error)) {

          // Save it and add it to the line item reference field's values array.
          commerce_line_item_save($line_item);

          // If the item is saved, we set a variable to notify the user the
          // need of saving the order.
          $form_state['line_item_save_warning'] = TRUE;
          $value[] = array(
            'line_item_id' => $line_item->line_item_id,
          );
        }
        else {

          // Otherwise display the error message; note this is not using
          // form_set_error() on purpose, because a failed addition of a line item
          // doesn't affect the rest of the form submission process.
          drupal_set_message($error, 'error');
        }
        $form_state['rebuild'] = TRUE;
      }
      elseif ($parent == 'cancel') {

        // If the cancel button was clicked refresh without action.
        $form_state['rebuild'] = TRUE;
      }
    }
  }
  form_set_value($element, $value, $form_state);
}