diff --git a/commerce_coupon.info b/commerce_coupon.info index 393f916..4c89a96 100644 --- a/commerce_coupon.info +++ b/commerce_coupon.info @@ -12,4 +12,5 @@ files[] = includes/views/handlers/commerce_coupon_handler_field_coupon_edit.inc files[] = includes/views/handlers/commerce_coupon_handler_field_coupon_link.inc files[] = includes/views/handlers/commerce_coupon_handler_argument_coupon_id.inc files[] = includes/views/handlers/commerce_coupon_handler_argument_coupon_code.inc +files[] = includes/views/handlers/commerce_coupon_handler_area_cart_form.inc files[] = commerce_coupon.info.inc \ No newline at end of file diff --git a/commerce_coupon.module b/commerce_coupon.module index c4b956e..32505d5 100644 --- a/commerce_coupon.module +++ b/commerce_coupon.module @@ -727,7 +727,7 @@ function commerce_coupon_redeem_coupon_code($code, $order, &$error) { $coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $coupon); - if (commerce_coupon_evaluate_conditions($coupon_wrapper, $order_wrapper)) { + if (empty($error) && commerce_coupon_evaluate_conditions($coupon_wrapper, $order_wrapper)) { // Add the coupon to the order. $order_wrapper->commerce_coupons[] = $coupon_wrapper->value(); diff --git a/includes/views/commerce_coupon.views.inc b/includes/views/commerce_coupon.views.inc index 4ad3f1f..d4bf067 100644 --- a/includes/views/commerce_coupon.views.inc +++ b/includes/views/commerce_coupon.views.inc @@ -74,6 +74,15 @@ function commerce_coupon_views_data_alter(&$data) { $data['commerce_coupon']['coupon_id']['argument'] = array( 'handler' => 'commerce_coupon_handler_argument_coupon_id' ); + + // Expose the coupon form on the cart form. + $data['commerce_order']['coupon_cart_form'] = array( + 'title' => t('Coupon cart form'), + 'help' => t('Coupon cart form'), + 'area' => array( + 'handler' => 'commerce_coupon_handler_area_cart_form', + ), + ); } } diff --git a/includes/views/handlers/commerce_coupon_handler_area_cart_form.inc b/includes/views/handlers/commerce_coupon_handler_area_cart_form.inc new file mode 100644 index 0000000..03e398b --- /dev/null +++ b/includes/views/handlers/commerce_coupon_handler_area_cart_form.inc @@ -0,0 +1,257 @@ + $view_value) { + // Only include line item Views. + if ($view_value->base_table == 'commerce_coupon') { + foreach ($view_value->display as $display_id => $display_value) { + $options[check_plain($view_id)][$view_id . '|' . $display_id] = check_plain($display_value->display_title); + } + } + } + + $form['coupon_cart_form_view'] = array( + '#type' => 'select', + '#title' => t('Coupons Cart View'), + '#description' => t('Specify the View to render the cart summary.'), + '#options' => array('none' => t('None')) + $options, + '#default_value' => $this->options['coupon_cart_form_view'], + ); + + $form['weight'] = array( + '#type' => 'textfield', + '#title' => t('Form item weight'), + '#default_value' => $this->options['weight'], + '#required' => TRUE, + ); + } + + function options_validate(&$form, &$form_state) { + $weight = $form_state['values']['options']['weight']; + // Weight must be an integer: + if (!is_null($weight )&& (!is_numeric($weight)) || (int) $weight != $weight) { + form_set_error('options][weight', t('!name field must be an integer.', array('!name' => $form['weight']['#title']))); + } + } + + function render($values) { + // Render a Views form item placeholder. + // This causes Views to wrap the View in a form. + return ''; + } + + /** + * This handler never outputs data when the view is empty. + */ + function views_form_empty($empty) { + return $empty; + } + + function views_form(&$form, &$form_state) { + + $form[$this->options['id']] = array( + '#prefix' => '
', + '#suffix' => '
', + '#weight' => $this->options['weight'], + ); + + $form[$this->options['id']]['coupon_code'] = array( + '#type' => 'textfield', + '#title' => t('Coupon code'), + '#description' => t('Enter your coupon code here.'), + ); + + $form[$this->options['id']]['coupon_add'] = array( + '#type' => 'submit', + '#value' => t('Add coupon'), + '#name' => 'coupon_add', + // '#limit_validation_errors' => array(), + '#validate' => array('commerce_coupon_handler_area_cart_form_validate'), + '#submit' => array('commerce_coupon_handler_area_cart_form_submit'), + ); + // Attach ajax if views ajax enabled. + // NOTE: shortcircuting this as ajax isn't working yet. + if (FALSE && $this->view->use_ajax) { + $form[$this->options['id']]['coupon_add']['#ajax'] = array( + 'callback' => 'commerce_coupon_cart_add_coupon_callback', + 'wrapper' => 'commerce-coupon-cart-form-wrapper', + ); + // Placeholder for any callback validation errors. + $form[$this->options['id']]['status_messages'] = array( + '#type' => 'markup', + '#markup' => '
', + '#weight' => -1, + ); + } + + // First look for an order_id argument. + foreach ($this->view->argument as $name => $argument) { + if ($argument instanceof commerce_order_handler_argument_order_order_id) { + // If it is single value... + if (count($argument->value) == 1) { + $order_id = reset($argument->value); + break; + } + } + } + $order = !empty($order_id) ? commerce_order_load($order_id) : commerce_cart_order_load($GLOBALS['user']->uid); + + // Extract the View and display keys from the cart contents pane setting. + $coupon_summary_view = $this->options['coupon_cart_form_view']; + if ($coupon_summary_view != 'none') { + list($view_id, $display_id) = explode('|', $coupon_summary_view); + if (!empty($view_id) && !empty($display_id) && views_get_view($view_id)) { + $form[$this->options['id']]['redeemed_coupons'] = array( + '#type' => 'markup', + '#markup' => commerce_embed_view($view_id, $display_id, array($order->order_id)), + ); + } + } + } +} + +/** + * Validate: function commerce_coupon_handler_area_cart_form + */ +function commerce_coupon_handler_area_cart_form_validate($form, $form_state) { + $coupon_code = $form_state['values']['coupon_code']; + $order = $form_state['order']; + + $error = ''; + + // No code provided + if (empty($coupon_code)) { + $error = t('Please enter a coupon code.'); + } + else { + // Check if the coupon code has already been applied. + $coupon = commerce_coupon_load_by_code($coupon_code); + + if (empty($coupon)) { + $error = t('Please enter a valid coupon code.'); + } + else { + // The same coupon cannot be added twice. + $order_wrapper = entity_metadata_wrapper('commerce_order', $order); + foreach ($order_wrapper->commerce_coupons as $order_coupon_wrapper) { + if ($order_coupon_wrapper->coupon_id->value() == $coupon->coupon_id) { + $error = t('The coupon you have entered has already been applied to your order'); + } + } + } + } + + // If a coupon was invalidated during the cart refresh (e.g. if its + // discounts failed their conditions), an error message will have been + // set. + if (empty($error)) { + $error = &drupal_static('commerce_coupon_error_' . strtolower($coupon_code)); + } + // If we have errors set the form error. + if (!empty($error)) { + form_set_error('coupon_code', $error); + } +} + +/** + * Submit: function commerce_coupon_handler_area_cart_form + * + * @todo Anyway to rollback redeeming a coupon if we find an error during + * redemption? + */ +function commerce_coupon_handler_area_cart_form_submit($form, $form_state) { + $coupon_code = $form_state['values']['coupon_code']; + $order = $form_state['order']; + + $error = ''; + + // Redeem the coupon. + $coupon = commerce_coupon_redeem_coupon_code($coupon_code, $order, $error); + $order = commerce_order_load($order->order_id); + + // Error found during redeem. + if (!empty($error)) { + watchdog('commerce_coupon', 'An error occurred redeeming a coupon: @error', array('@error' => $error), WATCHDOG_ERROR); + drupal_set_message('Unable to redeem coupon.'); + commerce_coupon_remove_coupon_from_order($order, $coupon); + } + + if ($coupon) { + // Allow modules/rules to act when a coupon has been successfully added + // to the cart. + rules_invoke_all('commerce_coupon_applied_to_cart', $coupon, $order); + } +} + +/** + * Ajax callback: coupon add button. + * + * @todo This logic is not working yet. + */ +function commerce_coupon_cart_add_coupon_callback($form, &$form_state) { + // We only execute this callback if the triggering element is the add to cart + // button. + if (!isset($form_state['triggering_element']) || $form_state['triggering_element']['#name'] != 'coupon_add') { + return; + } + + $coupon_code = $form_state['input']['coupon_code']; + $order = $form_state['order']; + + if ($errors = form_get_error('coupon_code')) { + drupal_set_message('testing'); + } + else { + // Reload the order so it is not out of date. + $order = commerce_order_load($order->order_id); + + // Recalculate discounts. + commerce_cart_order_refresh($order); + + // Re-render the cart form. + // This will also cause the coupon form and coupon summary view to re-render. + $view_id = variable_get('commerce_cart_view_override_page_view', 'commerce_cart_form'); + $display_id = 'default'; + // Generate a class to work with the ajax replace command. + // May also want to make this a view option in situations where views does not + // generate default classes. + $view_ajax_id = '.view-id-' . $view_id; + // Load the rendered view and ajax replace it. + $cart_form = commerce_embed_view($view_id, $display_id, array($order->order_id)); + $commands[] = ajax_command_replace($view_ajax_id, $cart_form); + } + + $commands[] = ajax_command_replace('#commerce-coupon-form-errors', theme('status_messages')); + + return array('#type' => 'ajax', '#commands' => $commands); +}