/** * Update the recurring payment method on a subscription order. * * @param array $available_gateways The payment gateways which are currently being allowed. * @since 1.4 */ private static function update_recurring_payment_method($subscription_key, $order, $new_payment_method) { global $woocommerce; $old_payment_method = $order->recurring_payment_method; $old_payment_method_title = $order->recurring_payment_method_title; $available_gateways = $woocommerce->payment_gateways->get_available_payment_gateways(); // Also inits all payment gateways to make sure that hooks are attached correctly do_action('woocommerce_subscriptions_pre_update_recurring_payment_method', $order, $subscription_key, $new_payment_method, $old_payment_method); // Make sure the subscription is cancelled with the current gateway WC_Subscriptions_Payment_Gateways::trigger_gateway_cancelled_subscription_hook($order->customer_user, $subscription_key); // Update meta update_post_meta($order->id, '_old_recurring_payment_method', $old_payment_method); update_post_meta($order->id, '_recurring_payment_method', $new_payment_method); if (isset($available_gateways[$new_payment_method])) { $new_payment_method_title = $available_gateways[$new_payment_method]->get_title(); } else { $new_payment_method_title = ''; } update_post_meta($order->id, '_old_recurring_payment_method_title', $old_payment_method_title); update_post_meta($order->id, '_recurring_payment_method_title', $new_payment_method_title); // Log change on order $order->add_order_note(sprintf(__('Recurring payment method changed from "%s" to "%s" by the subscriber from their account page.', 'woocommerce-subscriptions'), $old_payment_method_title, $new_payment_method_title)); do_action('woocommerce_subscriptions_updated_recurring_payment_method', $order, $subscription_key, $new_payment_method, $old_payment_method); do_action('woocommerce_subscriptions_updated_recurring_payment_method_to_' . $new_payment_method, $order, $subscription_key, $old_payment_method); do_action('woocommerce_subscriptions_updated_recurring_payment_method_from_' . $old_payment_method, $order, $subscription_key, $new_payment_method); }
do_action('cancelled_subscription_' . $order->recurring_payment_method, $order, $subscription['product_id']); } } /** * Fire a gateway specific hook when a subscription expires. * * @since 1.0 */ public static function trigger_gateway_subscription_expired_hook($user_id, $subscription_key) { $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key); $order = new WC_Order($subscription['order_id']); if (!WC_Subscriptions_Order::requires_manual_renewal($order)) { do_action('subscription_expired_' . $order->recurring_payment_method, $order, $subscription['product_id']); } } /** * Fired a gateway specific when a subscription was suspended. Suspended status was changed in 1.2 to match * WooCommerce with the "on-hold" status. * * @deprecated 1.2 * @since 1.0 */ public static function trigger_gateway_suspended_subscription_hook($user_id, $subscription_key) { _deprecated_function(__CLASS__ . '::' . __FUNCTION__, '1.2', __CLASS__ . '::trigger_gateway_subscription_put_on_hold_hook( $subscription_key, $user_id )'); self::trigger_gateway_subscription_put_on_hold_hook($subscription_key, $user_id); } } WC_Subscriptions_Payment_Gateways::init();
/** * Add a 'new-payment-method' handler to the @see WC_Subscription::can_be_updated_to() function * to determine whether the recurring payment method on a subscription can be changed. * * For the recurring payment method to be changeable, the subscription must be active, have future (automatic) payments * and use a payment gateway which allows the subscription to be cancelled. * * @param bool $subscription_can_be_changed Flag of whether the subscription can be changed to * @param string $new_status_or_meta The status or meta data you want to change th subscription to. Can be 'active', 'on-hold', 'cancelled', 'expired', 'trash', 'deleted', 'failed', 'new-payment-date' or some other value attached to the 'woocommerce_can_subscription_be_changed_to' filter. * @param object $args Set of values used in @see WC_Subscriptions_Manager::can_subscription_be_changed_to() for determining if a subscription can be changes, include: * 'subscription_key' string A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key() * 'subscription' array Subscription of the form returned by @see WC_Subscriptions_Manager::get_subscription() * 'user_id' int The ID of the subscriber. * 'order' WC_Order The order which recorded the successful payment (to make up for the failed automatic payment). * 'payment_gateway' WC_Payment_Gateway The subscription's recurring payment gateway * 'order_uses_manual_payments' bool A boolean flag indicating whether the subscription requires manual renewal payment. * @since 1.4 */ public static function can_subscription_be_updated_to_new_payment_method($subscription_can_be_changed, $subscription) { if (WC_Subscriptions_Payment_Gateways::one_gateway_supports('subscription_payment_method_change_customer') && $subscription->get_time('next_payment') > 0 && !$subscription->is_manual() && $subscription->payment_method_supports('subscription_cancellation') && $subscription->has_status('active')) { $subscription_can_be_changed = true; } else { $subscription_can_be_changed = false; } return $subscription_can_be_changed; }
/** * Allow subscription order items to be edited in WC 2.2. until Subscriptions 2.0 introduces * its own WC_Subscription object. * * @since 1.5.10 */ public static function is_order_editable($is_editable, $order) { if (false === $is_editable && self::order_contains_subscription($order)) { $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($order->id, '_recurring_payment_method', true)); $manual_renewal = self::requires_manual_renewal($order->id); // Only allow editing of subscriptions using a recurring payment method that supports changes if ('true' == $manual_renewal || false === $chosen_gateway || $chosen_gateway->supports('subscription_amount_changes') && $chosen_gateway->supports('subscription_date_changes')) { $backtrace = debug_backtrace(); $file_name = 'html-order-item.php'; // It's important we only allow the order item to be edited so that it must be saved with the order rather than via ajax (where there are no hooks to attach too) if ($file_name == substr($backtrace[3]['file'], -strlen($file_name))) { $is_editable = true; } } } return $is_editable; }
/** * Update recurring tax for subscriptions * Not executed if Subscriptions plugin is not active * * @since 4.4 * @return void */ function wootax_update_recurring_tax() { global $wpdb; // Exit if subs is not active if (!WT_SUBS_ACTIVE) { return; } // Find date/time 12 hours from now $twelve_hours = mktime(date('H') + 12); $date = new DateTime(date('c', $twelve_hours)); $date = $date->format('Y-m-d H:i:s'); // Set up logger $logger = false; if (WT_LOG_REQUESTS) { $logger = class_exists('WC_Logger') ? new WC_Logger() : WC()->logger(); $logger->add('wootax', 'Starting recurring tax update. Subscriptions with payments due before ' . $date . ' are being considered.'); } // Get all scheduled "scheduled_subscription_payment" actions with post_date <= $twelve_hours $scheduled = $wpdb->get_results($wpdb->prepare("SELECT ID, post_content FROM {$wpdb->posts} WHERE post_status = %s AND post_title = %s AND post_date <= %s", "pending", "scheduled_subscription_payment", $date)); // Update recurring totals if necessary if (count($scheduled) > 0) { // This will hold any warning messages that need to be sent to the admin $warnings = array(); foreach ($scheduled as $action) { $temp_warnings = array(); $show_warnings = false; // Run json_decode on post_content to extract user_id and subscription_key $args = json_decode($action->post_content); // Parse subscription_key to get order_id/product_id (format: ORDERID_PRODUCTID) $subscription_key = $args->subscription_key; $key_parts = explode('_', $subscription_key); $order_id = (int) $key_parts[0]; $product_id = (int) $key_parts[1]; if (get_post_status($order_id) == false) { continue; // Skip if the order no longer exists } // Determine if changes to subscription amounts are allowed by the current gateway $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($order_id, '_recurring_payment_method', true)); $manual_renewal = WC_Subscriptions_Order::requires_manual_renewal($order_id); $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? true : false; // Load order $order = WT_Orders::get_order($order_id); // Collect data for Lookup request $item_data = $type_array = array(); // Add subscription $product = WC_Subscriptions::get_product($product_id); // Get order item ID $item_id = $wpdb->get_var("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = '_product_id' AND im.meta_value = {$product_id} AND i.order_id = {$order_id}"); // Get price $recurring_subtotal = $order->get_item_meta($item_id, '_recurring_line_subtotal'); $regular_subtotal = $order->get_item_meta($item_id, '_line_subtotal'); $price = $recurring_subtotal === '0' || !empty($recurring_subtotal) ? $recurring_subtotal : $regular_subtotal; // Special case: If _subscription_sign_up_fee is set and $price is equal to its value, fall back to product price if ($order->get_item_meta($item_id, '_subscription_sign_up_fee') == $price) { $price = $product->get_price(); } $item_info = array('Index' => '', 'ItemID' => $item_id, 'Qty' => 1, 'Price' => $price, 'Type' => 'cart'); $tic = get_post_meta($product_id, 'wootax_tic', true); if (!empty($tic) && $tic) { $item_info['TIC'] = $tic; } $item_data[] = $item_info; $type_array[$item_id] = 'cart'; // Add recurring shipping items foreach ($order->order->get_items('recurring_shipping') as $item_id => $shipping) { $item_data[] = array('Index' => '', 'ItemID' => $item_id, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping['cost'], 'Type' => 'shipping'); $type_array[$item_id] = 'shipping'; } // Reset "captured" meta so lookup always sent $captured = WT_Orders::get_meta($order_id, 'captured'); WT_Orders::update_meta($order_id, 'captured', false); // Issue Lookup request $res = $order->do_lookup($item_data, $type_array, true); // Set "captured" back to original value WT_Orders::update_meta($order_id, 'captured', $captured); // If lookup is successful, use result to update recurring tax totals as described here: http://docs.woothemes.com/document/subscriptions/add-or-modify-a-subscription/#change-recurring-total if (is_array($res)) { // Find recurring tax item and determine original tax/shipping tax totals $wootax_item_id = $wpdb->get_var($wpdb->prepare("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = %s AND im.meta_value = %d AND i.order_id = %d AND i.order_item_type = %s", "rate_id", WT_RATE_ID, $order_id, "recurring_tax")); $old_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'tax_amount'); $old_shipping_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'shipping_tax_amount'); // Find new tax/shipping tax totals // Update _recurring_line_tax meta for each item $tax = $shipping_tax = 0; foreach ($res as $item) { $item_id = $item->ItemID; $item_tax = $item->TaxAmount; if ($type_array[$item_id] == 'shipping') { $shipping_tax += $item_tax; } else { $tax += $item_tax; } if ($changes_supported) { wc_update_order_item_meta($item_id, '_recurring_line_tax', $item_tax); wc_update_order_item_meta($item_id, '_recurring_line_subtotal_tax', $item_tax); } else { $temp_warnings[] = 'Recurring tax for item #' . $item_id . ' changed to ' . wc_round_tax_total($item_tax); } } // Update recurring tax if necessary if ($old_tax != $tax || $old_shipping_tax != $shipping_tax) { if ($changes_supported) { if (!empty($wootax_item_id)) { wc_update_order_item_meta($wootax_item_id, 'tax_amount', $tax); wc_update_order_item_meta($wootax_item_id, 'cart_tax', $tax); wc_update_order_item_meta($wootax_item_id, 'shipping_tax_amount', $shipping_tax); wc_update_order_item_meta($wootax_item_id, 'shipping_tax', $shipping_tax); } // Determine rounded difference in old/new tax totals $tax_diff = $tax + $shipping_tax - ($old_tax + $old_shipping_tax); $rounded_tax_diff = wc_round_tax_total($tax_diff); // Set new recurring total by adding difference between old and new tax to existing total $new_recurring_total = get_post_meta($order_id, '_order_recurring_total', true) + $rounded_tax_diff; update_post_meta($order_id, '_order_recurring_total', $new_recurring_total); if ($logger) { $logger->add('wootax', 'Set recurring total for order ' . $order_id . ' to: ' . $new_recurring_total); } } else { $temp_warnings[] = 'Total recurring tax changed from ' . wc_round_tax_total($old_tax) . ' to ' . wc_round_tax_total($tax); $temp_warnings[] = 'Total recurring shipping tax changed from ' . wc_round_tax_total($old_shipping_tax) . ' to ' . wc_round_tax_total($shipping_tax); $show_warnings = true; } } // Add to warnings array if necessary if ($show_warnings) { $warnings[$order_id] = $temp_warnings; } } } // Send out a single warning email to the admin if necessary // Ex: Email sent if a change in tax rates is detected and the gateway used by an order doesn't allow modification of sub. details if (count($warnings) > 0) { $email = wootax_get_notification_email(); if (!empty($email) && is_email($email)) { $subject = 'WooTax Warning: Recurring Tax Totals Need To Be Updated'; $message = 'Hello,' . "\r\n\r\n" . 'During a routine check on ' . date('m/d/Y') . ', WooTax discovered ' . count($warnings) . ' subscription orders whose recurring tax totals need to be updated. Unfortunately, the payment gateway(s) used for these orders does not allow subscription details to be altered, so the required changes must be implemented manually. All changes are listed below for your convenience.' . "\r\n\r\n"; foreach ($warnings as $order_id => $errors) { $message .= 'Order ' . $order_id . ': ' . "\r\n\r\n"; foreach ($errors as $error) { $message .= '- ' . $error . "\r\n"; } $message .= "\r\n\r\n"; } $message .= 'For assistance, please contact the WooTax support team at sales@wootax.com.'; wp_mail($email, $subject, $message); } } } else { if ($logger) { $logger->add('wootax', 'Ending recurring tax update. No subscriptions due before ' . $date . '.'); } } }
/** * In WC 2.0, settings are saved on a new instance of the PayPalpayment gateway, not * the global instance, so our admin fields are not set (nor saved). As a result, we * need to run the save routine @see WC_Settings_API::process_admin_options() again * to save our fields. * * @since 1.2.5 */ public static function save_subscription_form_fields() { $paypal_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway('paypal'); $paypal_gateway->process_admin_options(); }
/** * Get the new payment data from POST and check the new payment method supports * the new admin change hook. * * @since 2.0 * @param $subscription WC_Subscription */ public static function save_meta($subscription) { if (empty($_POST['_wcsnonce']) || !wp_verify_nonce($_POST['_wcsnonce'], 'wcs_change_payment_method_admin')) { return; } $payment_gateways = WC()->payment_gateways->payment_gateways(); $payment_method = isset($_POST['_payment_method']) ? wc_clean($_POST['_payment_method']) : ''; $payment_method_meta = apply_filters('woocommerce_subscription_payment_meta', array(), $subscription); $payment_method_meta = !empty($payment_method_meta[$payment_method]) ? $payment_method_meta[$payment_method] : array(); $valid_payment_methods = self::get_valid_payment_methods($subscription); if (!isset($valid_payment_methods[$payment_method])) { throw new Exception(__('Please choose a valid payment gateway to change to.', 'woocommerce-subscriptions')); } if (!empty($payment_method_meta)) { foreach ($payment_method_meta as $meta_table => &$meta) { if (!is_array($meta)) { continue; } foreach ($meta as $meta_key => &$meta_data) { $meta_data['value'] = isset($_POST['_payment_method_meta'][$meta_table][$meta_key]) ? $_POST['_payment_method_meta'][$meta_table][$meta_key] : ''; } } } $payment_gateway = 'manual' != $payment_method ? $payment_gateways[$payment_method] : ''; if (!$subscription->is_manual() && property_exists($subscription->payment_gateway, 'id') && ('' == $payment_gateway || $subscription->payment_gateway->id != $payment_gateway->id)) { // Before updating to a new payment gateway make sure the subscription status is updated with the current gateway $gateway_status = apply_filters('wcs_gateway_status_payment_changed', 'cancelled', $subscription, $payment_gateway); WC_Subscriptions_Payment_Gateways::trigger_gateway_status_updated_hook($subscription, $gateway_status); } $subscription->set_payment_method($payment_gateway, $payment_method_meta); }
/** * When a subscription is added to the cart, remove other products/subscriptions to * work with PayPal Standard, which only accept one subscription per checkout. * * If multiple purchase flag is set, allow them to be added at the same time. * * @since 1.0 */ public static function maybe_empty_cart($valid, $product_id, $quantity) { $is_subscription = WC_Subscriptions_Product::is_subscription($product_id); $cart_contains_subscription = WC_Subscriptions_Cart::cart_contains_subscription(); $multiple_subscriptions_possible = WC_Subscriptions_Payment_Gateways::one_gateway_supports('multiple_subscriptions'); $manual_renewals_enabled = 'yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals', 'no') ? true : false; if ($is_subscription && 'yes' != get_option(WC_Subscriptions_Admin::$option_prefix . '_multiple_purchase', 'no')) { WC()->cart->empty_cart(); } elseif ($is_subscription && wcs_cart_contains_renewal() && !$multiple_subscriptions_possible && !$manual_renewals_enabled) { self::remove_subscriptions_from_cart(); self::add_notice(__('A subscription renewal has been removed from your cart. Multiple subscriptions can not be purchased at the same time.', 'woocommerce-subscriptions'), 'notice'); } elseif ($is_subscription && $cart_contains_subscription && !$multiple_subscriptions_possible && !$manual_renewals_enabled) { self::remove_subscriptions_from_cart(); self::add_notice(__('A subscription has been removed from your cart. Due to payment gateway restrictions, different subscription products can not be purchased at the same time.', 'woocommerce-subscriptions'), 'notice'); } elseif ($cart_contains_subscription && 'yes' != get_option(WC_Subscriptions_Admin::$option_prefix . '_multiple_purchase', 'no')) { self::remove_subscriptions_from_cart(); self::add_notice(__('A subscription has been removed from your cart. Products and subscriptions can not be purchased at the same time.', 'woocommerce-subscriptions'), 'notice'); // Redirect to cart page to remove subscription & notify shopper add_filter('add_to_cart_fragments', __CLASS__ . '::redirect_ajax_add_to_cart'); } return $valid; }
/** * Settings are saved on a new instance of the PayPal payment gateway, not the global * instance, so our admin fields are not set (nor saved). As a result, we need to run * the save routine @see WC_Settings_API::process_admin_options() again to save our fields. * * @since 1.2.5 */ public static function save_subscription_form_fields() { // WC 2.2 added its own API fields so this is no longer necessary if (WC_Subscriptions::is_woocommerce_pre_2_2()) { $paypal_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway('paypal'); $paypal_gateway->process_admin_options(); } }
/** * Process the renewal action from the Subscriptions list table for * 1.5.x * * @since 0.2.0 */ public function process_pre_subs_2_0_renew_action() { // data check if (empty($_GET['action']) || empty($_GET['_wpnonce']) || 'renew' !== $_GET['action'] || empty($_GET['user']) || empty($_GET['subscription'])) { return; } // nonce check if (!wp_verify_nonce($_REQUEST['_wpnonce'], $_GET['subscription'])) { wp_die(__('Action Failed, Invalid Nonce', 'woocommerce-dev-helper')); } // load gateways WC()->payment_gateways(); // trigger the renewal payment WC_Subscriptions_Payment_Gateways::gateway_scheduled_subscription_payment(absint($_GET['user']), $_GET['subscription']); // success message add_filter('woocommerce_subscriptions_list_table_pre_process_actions', array($this, 'maybe_render_pre_subs_2_0_renewal_success_message')); }
/** * Display recurring order totals on the "Edit Order" page. * * @param int $post_id The post ID of the shop_order post object. * @since 1.2.4 * @return void */ public static function recurring_order_totals_meta_box_section($post_id) { global $woocommerce, $wpdb; $order = new WC_Order($post_id); $display_none = ' style="display: none"'; $contains_subscription = self::order_contains_subscription($order) ? true : false; $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($post_id, '_recurring_payment_method', true)); $manual_renewal = self::requires_manual_renewal($post_id); $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? 'true' : 'false'; $data = get_post_meta($post_id); ?> <div class="clear"></div> </div> <div id="gateway_support"<?php if (!$contains_subscription) { echo $display_none; } ?> > <input type="hidden" name="gateway_supports_subscription_changes" value="<?php echo $changes_supported; ?> "> <div class="error"<?php if (!$contains_subscription || $changes_supported == 'true') { echo $display_none; } ?> > <p><?php printf(__('The %s payment gateway is used to charge automatic subscription payments for this order. This gateway <strong>does not</strong> support changing a subscription\'s details.', 'woocommerce-subscriptions'), get_post_meta($post_id, '_recurring_payment_method_title', true)); ?> </p> <p> <?php _e('It is strongly recommended you <strong>do not change</strong> any of the recurring totals or subscription item\'s details.', 'woocommerce-subscriptions'); ?> <a href="http://docs.woothemes.com/document/subscriptions/add-or-modify-a-subscription/#section-4"><?php _e('Learn More', 'woocommerce-subscriptions'); ?> »</a> </p> </div> </div> <div id="recurring_order_totals"<?php if (!$contains_subscription) { echo $display_none; } ?> > <h3><?php _e('Recurring Totals', 'woocommerce-subscriptions'); ?> </h3> <div class="totals_group"> <h4><span class="tax_total_display inline_total"></span><?php _e('Shipping for Renewal Orders', 'woocommerce-subscriptions'); ?> </h4> <div id="recurring_shipping_rows"> <?php if (!WC_Subscriptions::is_woocommerce_pre_2_1()) { if ($woocommerce->shipping()) { $shipping_methods = $woocommerce->shipping->load_shipping_methods(); } foreach (self::get_recurring_shipping_methods($order) as $item_id => $item) { $chosen_method = $item['method_id']; $shipping_title = $item['name']; $shipping_cost = $item['cost']; include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-shipping-html.php'; } // Shipping created pre 2.1 if (isset($data['_recurring_shipping_method'])) { $item_id = 'old'; // so that when saving, we know to delete the data in the old form $chosen_method = !empty($data['_recurring_shipping_method'][0]) ? $data['_recurring_shipping_method'][0] : ''; $shipping_title = !empty($data['_recurring_shipping_method_title'][0]) ? $data['_recurring_shipping_method_title'][0] : ''; $shipping_cost = !empty($data['_order_recurring_shipping_total'][0]) ? $data['_order_recurring_shipping_total'][0] : '0.00'; include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-shipping-html.php'; } ?> <?php } else { // WC < 2.1 ?> <ul class="totals"> <li class="wide"> <label><?php _e('Label:', 'woocommerce-subscriptions'); ?> </label> <input type="text" id="_recurring_shipping_method_title" name="_recurring_shipping_method_title" placeholder="<?php _e('The shipping title for renewal orders', 'woocommerce-subscriptions'); ?> " value="<?php echo $order->recurring_shipping_method_title; ?> " class="first" /> </li> <li class="left"> <label><?php _e('Cost:', 'woocommerce-subscriptions'); ?> </label> <input type="text" id="_order_recurring_shipping_total" name="_order_recurring_shipping_total" placeholder="0.00 <?php _e('(ex. tax)', 'woocommerce-subscriptions'); ?> " value="<?php echo self::get_recurring_shipping_total($order); ?> " class="first" /> </li> <li class="right"> <label><?php _e('Method:', 'woocommerce-subscriptions'); ?> </label> <select name="_recurring_shipping_method" id="_recurring_shipping_method" class="first"> <option value=""><?php _e('N/A', 'woocommerce-subscriptions'); ?> </option> <?php $chosen_shipping_method = $order->recurring_shipping_method; $found_method = false; if ($woocommerce->shipping()) { foreach ($woocommerce->shipping->load_shipping_methods() as $method) { if (strpos($chosen_shipping_method, $method->id) === 0) { $value = $chosen_shipping_method; } else { $value = $method->id; } echo '<option value="' . esc_attr($value) . '" ' . selected($chosen_shipping_method == $value, true, false) . '>' . esc_html($method->get_title()) . '</option>'; if ($chosen_shipping_method == $value) { $found_method = true; } } } if (!$found_method && !empty($chosen_shipping_method)) { echo '<option value="' . esc_attr($chosen_shipping_method) . '" selected="selected">' . __('Other', 'woocommerce-subscriptions') . '</option>'; } else { echo '<option value="other">' . __('Other', 'woocommerce-subscriptions') . '</option>'; } ?> </select> </li> </ul> <?php } // ! WC_Subscriptions::is_woocommerce_pre_2_1() ?> </div> <div class="clear"></div> </div> <?php if ('yes' == get_option('woocommerce_calc_taxes')) { ?> <div class="totals_group tax_rows_group"> <h4> <span class="tax_total_display inline_total"></span> <?php _e('Recurring Taxes', 'woocommerce-subscriptions'); ?> <a class="tips" data-tip="<?php _e('These rows contain taxes included in each recurring amount for this subscription. This allows you to display multiple or compound taxes rather than a single total on future subscription renewal orders.', 'woocommerce-subscriptions'); ?> " href="#">[?]</a> </h4> <div id="recurring_tax_rows" class="total_rows"> <?php $loop = 0; $taxes = self::get_recurring_taxes($order); if (is_array($taxes) && sizeof($taxes) > 0) { $rates = $wpdb->get_results("SELECT tax_rate_id, tax_rate_country, tax_rate_state, tax_rate_name, tax_rate_priority FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name"); $tax_codes = array(); foreach ($rates as $rate) { $code = array(); $code[] = $rate->tax_rate_country; $code[] = $rate->tax_rate_state; $code[] = $rate->tax_rate_name ? sanitize_title($rate->tax_rate_name) : 'TAX'; $code[] = absint($rate->tax_rate_priority); $tax_codes[$rate->tax_rate_id] = strtoupper(implode('-', array_filter($code))); } foreach ($taxes as $item_id => $item) { include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php'; $loop++; } } ?> </div> <h4 style="padding-bottom: 10px;"><a href="#" class="add_recurring_tax_row"><?php _e('+ Add tax row', 'woocommerce-subscriptions'); ?> </a></h4> <div class="clear"></div> </div> <?php if (WC_Subscriptions::is_woocommerce_pre_2_1()) { ?> <div class="totals_group"> <h4><span class="tax_total_display inline_total"></span><?php _e('Tax Totals', 'woocommerce-subscriptions'); ?> </h4> <ul class="totals"> <li class="left"> <label><?php _e('Recurring Sales Tax:', 'woocommerce-subscriptions'); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_tax_total" name="_order_recurring_tax_total" placeholder="0.00" value="<?php echo self::get_recurring_total_tax($order); ?> " class="calculated" /> </li> <li class="right"> <label><?php _e('Shipping Tax:', 'woocommerce-subscriptions'); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_shipping_tax_total" name="_order_recurring_shipping_tax_total" placeholder="0.00" value="<?php echo self::get_recurring_shipping_tax_total($order); ?> " class="calculated" /> </li> </ul> <div class="clear"></div> </div> <?php } // WC_Subscriptions::is_woocommerce_pre_2_1() ?> <?php } ?> <div class="totals_group"> <h4><label for="_order_recurring_discount_total"><?php _e('Recurring Order Discount', 'woocommerce-subscriptions'); ?> <a class="tips" data-tip="<?php _e('The discounts applied to each recurring payment charged in the future.', 'woocommerce-subscriptions'); ?> " href="#">[?]</a></label></h4> <input type="text" class="wc_input_price" id="_order_recurring_discount_total" name="_order_recurring_discount_total" placeholder="0.00" value="<?php echo self::get_recurring_discount_total($order); ?> " style="margin: 6px 0 10px;"/> </div> <div class="totals_group"> <h4><label for="_order_recurring_total"><?php _e('Recurring Order Total', 'woocommerce-subscriptions'); ?> <a class="tips" data-tip="<?php _e('The total amounts charged for each future recurring payment.', 'woocommerce-subscriptions'); ?> " href="#">[?]</a></label></h4> <input type="text" id="_order_recurring_total" name="_order_recurring_total" placeholder="0.00" value="<?php echo self::get_recurring_total($order); ?> " class="calculated" style="margin: 6px 0 10px;"/> </div> <div class="totals_group"> <h4><?php _e('Recurring Payment Method:', 'woocommerce-subscriptions'); ?> </h4> <div style="padding-top: 4px; font-style: italic; margin: 2px 0 10px;"><?php echo $manual_renewal || empty($order->recurring_payment_method_title) ? __('Manual', 'woocommerce-subscriptions') : $order->recurring_payment_method_title; ?> </div> </div> <?php }
/** * Display recurring order totals on the "Edit Order" page. * * @param $post_id int The post ID of the shop_order post object. * @since 1.2.4 * @return void */ public static function recurring_order_totals_meta_box_section($post_id) { global $woocommerce, $wpdb; $order = new WC_Order($post_id); $display_none = ' style="display: none"'; $contains_subscription = WC_Subscriptions_Order::order_contains_subscription($order) ? true : false; $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($post_id, '_payment_method', true)); $manual_renewal = self::requires_manual_renewal($post_id); $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? 'true' : 'false'; ?> <p id="recurring_shipping_description"<?php if (!$contains_subscription) { echo $display_none; } ?> > <?php _e('Shipping cost is included in the recurring total.', WC_Subscriptions::$text_domain); ?> </p> <div class="clear"></div> </div> <div id="gateway_support"<?php if (!$contains_subscription) { echo $display_none; } ?> > <input type="hidden" name="gateway_supports_subscription_changes" value="<?php echo $changes_supported; ?> "> <div class="error"<?php if (!$contains_subscription || $changes_supported == 'true') { echo $display_none; } ?> > <p><?php printf(__('The %s payment gateway is used to charge automatic subscription payments for this order. This gateway <strong>does not</strong> support changing a subscription\'s details.', WC_Subscriptions::$text_domain), get_post_meta($post_id, '_payment_method_title', true)); ?> </p> <p> <?php _e('It is strongly recommended you <strong>do not change</strong> any of the recurring totals or subscription item\'s details.', WC_Subscriptions::$text_domain); ?> <a href="http://docs.woothemes.com/document/add-or-modify-a-subscription/#section-4"><?php _e('Learn More', WC_Subscriptions::$text_domain); ?> »</a> </p> </div> </div> <div id="recurring_order_totals"<?php if (!$contains_subscription) { echo $display_none; } ?> > <h3><?php _e('Recurring Totals', WC_Subscriptions::$text_domain); ?> </h3> <div class="totals_group"> <h4><?php _e('Recurring Discounts', WC_Subscriptions::$text_domain); ?> <a class="tips" data-tip="<?php _e('The discounts applied to each recurring payment charged in the future.', WC_Subscriptions::$text_domain); ?> " href="#">[?]</a></h4> <ul class="totals"> <li class="left"> <label><?php _e('Cart Discount:', WC_Subscriptions::$text_domain); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_discount_cart" name="_order_recurring_discount_cart" placeholder="0.00" value="<?php echo self::get_recurring_discount_cart($order); ?> " class="calculated" /> </li> <li class="right"> <label><?php _e('Order Discount:', WC_Subscriptions::$text_domain); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_discount_total" name="_order_recurring_discount_total" placeholder="0.00" value="<?php echo self::get_recurring_discount_total($order); ?> " /> </li> </ul> <div class="clear"></div> </div> <div class="totals_group tax_rows_group"> <h4><?php _e('Recurring Tax Rows', WC_Subscriptions::$text_domain); ?> <a class="tips" data-tip="<?php _e('These rows contain taxes included in each recurring amount for this subscription. This allows you to display multiple or compound taxes rather than a single total on future subscription renewal orders.', WC_Subscriptions::$text_domain); ?> " href="#">[?]</a></h4> <div id="recurring_tax_rows"> <?php $loop = 0; $taxes = self::get_recurring_taxes($order); if (is_array($taxes) && sizeof($taxes) > 0) { if (function_exists('woocommerce_add_order_item_meta')) { // WC 2.0+ $rates = $wpdb->get_results("SELECT tax_rate_id, tax_rate_country, tax_rate_state, tax_rate_name, tax_rate_priority FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name"); $tax_codes = array(); foreach ($rates as $rate) { $code = array(); $code[] = $rate->tax_rate_country; $code[] = $rate->tax_rate_state; $code[] = $rate->tax_rate_name ? sanitize_title($rate->tax_rate_name) : 'TAX'; $code[] = absint($rate->tax_rate_priority); $tax_codes[$rate->tax_rate_id] = strtoupper(implode('-', array_filter($code))); } } foreach ($taxes as $item_id => $item) { ?> <?php if (isset($item['name'])) { // WC 2.0+ ?> <?php include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php'; ?> <?php } else { // WC 1.x ?> <div class="tax_row"> <p class="first"> <label><?php _e('Recurring Tax Label:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $loop; ?> ][label]" placeholder="<?php echo $woocommerce->countries->tax_or_vat(); ?> " value="<?php echo $item['label']; ?> " /> </p> <p class="last"> <label><?php _e('Compound:', WC_Subscriptions::$text_domain); ?> <input type="checkbox" name="_order_recurring_taxes[<?php echo $loop; ?> ][compound]" <?php checked($item['compound'], 1); ?> /></label> </p> <p class="first"> <label><?php _e('Recurring Cart Tax:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $loop; ?> ][cart_tax]" placeholder="0.00" value="<?php echo $item['cart_tax']; ?> " /> </p> <p class="last"> <label><?php _e('Shipping Tax:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $loop; ?> ][shipping_tax]" placeholder="0.00" value="<?php echo $item['shipping_tax']; ?> " /> </p> <a href="#" class="delete_tax_row">×</a> <div class="clear"></div> </div> <?php } ?> <?php $loop++; } } ?> </div> <h4 style="padding-bottom: 10px;"><a href="#" class="add_recurring_tax_row"><?php _e('+ Add tax row', WC_Subscriptions::$text_domain); ?> </a></h4> <div class="clear"></div> </div> <div class="totals_group"> <h4><?php _e('Recurring Totals', WC_Subscriptions::$text_domain); ?> <a class="tips" data-tip="<?php _e('The total amounts charged for each future recurring payment.', WC_Subscriptions::$text_domain); ?> " href="#">[?]</a></h4> <ul class="totals"> <li class="left"> <label><?php _e('Recurring Tax Total:', WC_Subscriptions::$text_domain); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_tax_total" name="_order_recurring_tax_total" placeholder="0.00" value="<?php echo self::get_recurring_total_tax($order); ?> " class="calculated" /> </li> <li class="right"> <label><?php _e('Recurring Order Total:', WC_Subscriptions::$text_domain); ?> </label> <input type="number" step="any" min="0" id="_order_recurring_total" name="_order_recurring_total" placeholder="0.00" value="<?php echo self::get_recurring_total($order); ?> " class="calculated" /> </li> </ul> <div class="clear"></div> </div> <?php }