diff --git a/modules/cart/commerce_cart.info b/modules/cart/commerce_cart.info index d7195fc..a59be05 100644 --- a/modules/cart/commerce_cart.info +++ b/modules/cart/commerce_cart.info @@ -15,6 +15,7 @@ core = 7.x ; Views handlers files[] = includes/views/handlers/commerce_cart_handler_field_add_to_cart_form.inc +files[] = includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc files[] = includes/views/handlers/commerce_cart_plugin_argument_default_current_cart_order_id.inc files[] = includes/views/handlers/commerce_cart_handler_area_empty_text.inc diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index 77c90f8..93b2e11 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -2369,6 +2369,16 @@ function commerce_cart_add_to_cart_form_attributes_refresh($form, $form_state) { } /** + * Ajax callback: returns AJAX commands when an attribute widget is changed on + * the Views powered shopping cart form. + */ +function commerce_cart_add_to_cart_views_form_refresh($form, $form_state) { + $commands[] = array(); + $commands[] = ajax_command_replace('.' . drupal_html_class('commerce-line-item-views-form'), drupal_render($form)); + return array('#type' => 'ajax', '#commands' => $commands); +} + +/** * Form submit handler: add the selected product to the cart. */ function commerce_cart_add_to_cart_form_submit($form, &$form_state) { diff --git a/modules/cart/includes/views/commerce_cart.views.inc b/modules/cart/includes/views/commerce_cart.views.inc index 4ced3f0..8d4b909 100644 --- a/modules/cart/includes/views/commerce_cart.views.inc +++ b/modules/cart/includes/views/commerce_cart.views.inc @@ -29,6 +29,15 @@ function commerce_cart_views_data_alter(&$data) { 'handler' => 'commerce_cart_handler_area_empty_text', ), ); + + // Add an edit handler for cart line item attributes. + $data['commerce_line_item']['edit_attributes'] = array( + 'field' => array( + 'title' => t('Attribute field widgets'), + 'help' => t('Renders attribute field widgets for customers to edit from the View.'), + 'handler' => 'commerce_cart_handler_field_edit_attributes', + ), + ); } /** diff --git a/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc b/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc new file mode 100644 index 0000000..b5b1bda --- /dev/null +++ b/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc @@ -0,0 +1,105 @@ +additional_fields['line_item_id'] = 'line_item_id'; + + // Set real_field in order to make it generate a field_alias. + $this->real_field = 'line_item_id'; + } + + function render($values) { + return ''; + } + + /** + * Returns the form which replaces the placeholder from render(). + */ + function views_form(&$form, &$form_state) { + // The view is empty, abort. + if (empty($this->view->result)) { + return; + } + + $form[$this->options['id']] = array( + '#tree' => TRUE, + ); + + // At this point, the query has already been run, so we can access the + // results in order to get the base key value (for example, nid for nodes). + foreach ($this->view->result as $row_id => $row) { + // Load the line item and generate a form ID based on its context data. + $line_item = commerce_line_item_load($this->get_value($row, 'line_item_id')); + $product_ids = commerce_cart_add_to_cart_form_product_ids($line_item); + $form_id = commerce_cart_add_to_cart_form_id($product_ids); + + // Fetch the Add to Cart form and put the attributes section into this + // field's part of the form if it exists. + $subform_state = $form_state; + $subform_state['build_info'] = array( + 'form_id' => $form_id, + 'base_form_id' => 'commerce_cart_add_to_cart_form', + 'args' => array($line_item), + ); + + // If the form has been submitted, copy the attributes values from the + // edit_attributes sub-array to the top level of the submitted values + // array so the selected product can be properly matched when the Add to + // Cart form builds itself. + if (!empty($form_state['values']['edit_attributes'][$row_id])) { + $subform_state['values'] += $form_state['values']['edit_attributes'][$row_id]; + } + + $subform = array(); + $subform = commerce_cart_add_to_cart_form($subform, $subform_state, $line_item); + + // If an Ajax refresh resulted in an updated product ID, update the line + // item accordingly and rebuild the subform. + $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item); + + if ($subform['product_id']['#value'] != $line_item_wrapper->commerce_product->raw()) { + $line_item_wrapper->commerce_product = $subform['product_id']['#value']; + $line_item_wrapper->save(); + $form_state['rebuild'] = TRUE; + + $subform_state = $form_state; + $subform_state['build_info'] = array( + 'form_id' => $form_id, + 'base_form_id' => 'commerce_cart_add_to_cart_form', + 'args' => array($line_item), + ); + + $subform = array(); + $subform = commerce_cart_add_to_cart_form($subform, $subform_state, $line_item); + } + + // Initialize the element representing the attribute fields in the form. + $form[$this->options['id']][$row_id] = array(); + $element = &$form[$this->options['id']][$row_id]; + + foreach (array('attributes', 'unchanged_attributes', 'product_id') as $name) { + if (!empty($subform[$name])) { + $element[$name] = $subform[$name]; + + if (!empty($element[$name]['#ajax']['callback'])) { + $element[$name]['#ajax']['callback'] = 'commerce_cart_add_to_cart_views_form_refresh'; + } + + foreach (element_children($element[$name]) as $key) { + if (!empty($element[$name][$key]['#ajax']['callback'])) { + $element[$name][$key]['#ajax']['callback'] = 'commerce_cart_add_to_cart_views_form_refresh'; + } + } + } + } + } + } +} \ No newline at end of file