/**
  * When an order is added or updated from the admin interface, check if a new subscription product
  * has been manually added to the order, and if one has, create a new subscription. 
  * 
  * @param $post_id int The ID of the post which is the WC_Order object.
  * @param $post Object The post object of the order.
  * @since 1.1
  */
 public static function maybe_manually_change_subscriptions($post_id, $post)
 {
     $order = new WC_Order($post_id);
     // Check if all the subscription products on the order have associated subscriptions on the user's account, and if not, add a new one
     foreach ($_POST['item_id'] as $item_id) {
         if (!WC_Subscriptions_Product::is_subscription($item_id)) {
             continue;
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($post_id, $item_id);
         $subscription = array();
         // If order customer changed, move the subscription from the old customer's account to the new customer
         if (!empty($order->customer_user) && $order->customer_user != (int) $_POST['customer_user']) {
             $subscription = WC_Subscriptions_Manager::remove_users_subscription($order->customer_user, $subscription_key);
             $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions((int) $_POST['customer_user']);
             if (!empty($subscription)) {
                 $subscriptions[$subscription_key] = $subscription;
                 WC_Subscriptions_Manager::update_users_subscriptions((int) $_POST['customer_user'], $subscriptions);
             }
         }
         // In case it's a new order or the customer has changed
         $order->customer_user = $order->user_id = (int) $_POST['customer_user'];
         $subscription = WC_Subscriptions_Manager::get_users_subscription($order->customer_user, $subscription_key);
         if (empty($subscription)) {
             // Add a new subscription
             // The order doesn't may not exist yet, so we need to set a few things ourselves
             $order->order_key = uniqid('order_');
             add_post_meta($post_id, '_order_key', $order->order_key, true);
             WC_Subscriptions_Manager::create_pending_subscription_for_order($order, $item_id);
             // Add the subscription meta for this item to the order
             $functions_and_meta = array('get_period' => '_order_subscription_periods', 'get_interval' => '_order_subscription_intervals', 'get_length' => '_order_subscription_lengths');
             foreach ($functions_and_meta as $function_name => $meta_key) {
                 $subscription_meta = self::get_meta($order, $meta_key, array());
                 $subscription_meta[$item_id] = WC_Subscriptions_Product::$function_name($item_id);
                 update_post_meta($order->id, $meta_key, $subscription_meta);
             }
             // Set the subscription's status if it should be something other than pending
             switch ($order->status) {
                 case 'completed':
                 case 'processing':
                     WC_Subscriptions_Manager::activate_subscription($order->customer_user, $subscription_key);
                     break;
                 case 'refunded':
                 case 'cancelled':
                     WC_Subscriptions_Manager::cancel_subscription($order->customer_user, $subscription_key);
                     break;
                 case 'failed':
                     WC_Subscriptions_Manager::failed_subscription_signup($order->customer_user, $subscription_key);
                     break;
             }
         }
     }
 }
 /**
  * Handle activate & cancel actions for both individual items and bulk edit. 
  *
  * @since 1.0
  */
 public function process_actions()
 {
     $custom_actions = apply_filters('woocommerce_subscriptions_list_table_pre_process_actions', array('custom_action' => false, 'messages' => array(), 'error_messages' => array()));
     if ($this->current_action() === false && $custom_actions['custom_action'] === false) {
         return;
     }
     $messages = array();
     $error_messages = array();
     $query_args = array();
     // Check if custom actions were taken by the filter - if so, it has handled the action and we only need to set the message/error messages
     if ($custom_actions['custom_action'] !== false) {
         $messages = $custom_actions['messages'];
         $error_messages = $custom_actions['error_messages'];
     } else {
         if (isset($_GET['subscription'])) {
             // Single subscription action
             if (!wp_verify_nonce($_REQUEST['_wpnonce'], $_GET['subscription'])) {
                 wp_die(__('Action failed. Invalid Nonce.', WC_Subscriptions::$text_domain));
             }
             if (!WC_Subscriptions_Manager::can_subscription_be_changed_to($_GET['new_status'], $_GET['subscription'], $_GET['user'])) {
                 $error_messages[] = sprintf(__('Error: Subscription status can not be changed to "%s".', WC_Subscriptions::$text_domain), esc_html($_GET['new_status']));
             } else {
                 switch ($_GET['new_status']) {
                     case 'active':
                         WC_Subscriptions_Manager::reactivate_subscription($_GET['user'], $_GET['subscription']);
                         $messages[] = __('Subscription activated.', WC_Subscriptions::$text_domain);
                         break;
                     case 'on-hold':
                         WC_Subscriptions_Manager::put_subscription_on_hold($_GET['user'], $_GET['subscription']);
                         $messages[] = __('Subscription put on-hold.', WC_Subscriptions::$text_domain);
                         break;
                     case 'cancelled':
                         WC_Subscriptions_Manager::cancel_subscription($_GET['user'], $_GET['subscription']);
                         $messages[] = __('Subscription cancelled.', WC_Subscriptions::$text_domain);
                         break;
                     case 'trash':
                         WC_Subscriptions_Manager::trash_subscription($_GET['user'], $_GET['subscription']);
                         $messages[] = __('Subscription trashed.', WC_Subscriptions::$text_domain);
                         break;
                     case 'deleted':
                         WC_Subscriptions_Manager::delete_subscription($_GET['user'], $_GET['subscription']);
                         $messages[] = __('Subscription deleted.', WC_Subscriptions::$text_domain);
                         break;
                     default:
                         $error_messages[] = __('Error: Unknown subscription status.', WC_Subscriptions::$text_domain);
                         break;
                 }
             }
         } else {
             if (isset($_GET['subscription_keys'])) {
                 // Bulk actions
                 if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'bulk-' . $this->_args['plural'])) {
                     wp_die(__('Bulk edit failed. Invalid Nonce.', WC_Subscriptions::$text_domain));
                 }
                 $subscriptions = $_GET['subscription_keys'];
                 $subscription_count = 0;
                 $error_count = 0;
                 if (in_array($this->current_action(), array('trash', 'deleted'))) {
                     foreach ($subscriptions as $user_id => $subscription_keys) {
                         foreach ($subscription_keys as $subscription_key) {
                             if (!WC_Subscriptions_Manager::can_subscription_be_changed_to($this->current_action(), $subscription_key, $user_id)) {
                                 $error_count++;
                             } else {
                                 $subscription_count++;
                                 if ('trash' == $this->current_action()) {
                                     WC_Subscriptions_Manager::trash_subscription($user_id, $subscription_key);
                                 } else {
                                     WC_Subscriptions_Manager::delete_subscription($user_id, $subscription_key);
                                 }
                             }
                         }
                     }
                     if ($subscription_count > 0) {
                         if ('trash' == $this->current_action()) {
                             $messages[] = sprintf(_n('%d subscription moved to trash.', '%s subscriptions moved to trash.', $subscription_count, WC_Subscriptions::$text_domain), $subscription_count);
                         } else {
                             $messages[] = sprintf(_n('%d subscription deleted.', '%s subscriptions deleted.', $subscription_count, WC_Subscriptions::$text_domain), $subscription_count);
                         }
                     }
                     if ($error_count > 0) {
                         if ('trash' == $this->current_action()) {
                             $error_messages[] = sprintf(_n('%d subscription could not be trashed - is it active or on-hold? Try cancelling it before trashing it.', '%s subscriptions could not be trashed - are they active or on-hold? Try cancelling them before trashing.', $error_count, WC_Subscriptions::$text_domain), $error_count);
                         } else {
                             $error_messages[] = sprintf(_n('%d subscription could not deleted - is it active or on-hold? Try cancelling it before deleting.', '%s subscriptions could not deleted - are they active or on-hold? Try cancelling them before deleting.', $error_count, WC_Subscriptions::$text_domain), $error_count);
                         }
                     }
                 }
             }
         }
     }
     $message_nonce = wp_create_nonce(__FILE__);
     set_transient($this->message_transient_prefix . $message_nonce, array('messages' => $messages, 'error_messages' => $error_messages), 60 * 60);
     // Filter by a given customer or product?
     if (isset($_GET['_customer_user']) || isset($_GET['_product_id'])) {
         if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'bulk-subscriptions')) {
             wp_die(__('Action failed. Invalid Nonce.', WC_Subscriptions::$text_domain));
         }
         if (!empty($_GET['_customer_user'])) {
             $user_id = intval($_GET['_customer_user']);
             $user = get_user_by('id', absint($_GET['_customer_user']));
             if (false === $user) {
                 wp_die(__('Action failed. Invalid user ID.', WC_Subscriptions::$text_domain));
             }
             $query_args['_customer_user'] = $user_id;
         }
         if (!empty($_GET['_product_id'])) {
             $product_id = intval($_GET['_product_id']);
             $product = get_product($product_id);
             if (false === $product) {
                 wp_die(__('Action failed. Invalid product ID.', WC_Subscriptions::$text_domain));
             }
             $query_args['_product_id'] = $product_id;
         }
     }
     $status = isset($_GET['status']) ? $_GET['status'] : 'all';
     $query_args = array_merge($query_args, array('status' => $status, 'message' => $message_nonce));
     $search_query = _admin_search_query();
     if (!empty($search_query)) {
         $query_args['s'] = $search_query;
     }
     $redirect_to = add_query_arg($query_args, admin_url('admin.php?page=subscriptions'));
     // Redirect to avoid performning actions on a page refresh
     wp_safe_redirect($redirect_to);
     exit;
 }
Пример #3
0
function paymill_webhooks()
{
    global $wpdb;
    // is there a webhook from Paymill?
    if (class_exists('WC_Subscriptions_Manager')) {
        // grab data from webhook
        $body = @file_get_contents('php://input');
        $event_json = json_decode($body, true);
        // retrieve sub ID
        if (isset($event_json['event']['event_resource']['id']) && strlen($event_json['event']['event_resource']['id']) > 0) {
            $paymill_sub_id = $event_json['event']['event_resource']['id'];
        } elseif (isset($event_json['event']['event_resource']['subscription']['id']) && strlen($event_json['event']['event_resource']['subscription']['id']) > 0) {
            $paymill_sub_id = $event_json['event']['event_resource']['subscription']['id'];
        }
        error_log("\n\n########################################################################################################################\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
        error_log(date(DATE_RFC822) . ' - Webhook ' . $event_json['event']['event_type'] . ' (Resource-ID: ' . $paymill_sub_id . ') triggered - start processing' . "\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
        /* output example:
        				array(1) {
        				  ["event"]=>
        				  array(4) {
        					["event_type"]=>
        					string(20) "subscription.deleted"
        					["event_resource"]=>
        					array(13) {
        					  ["id"]=>
        					  string(24) "sub_b71adbf5....."
        					  ["offer"]=>
        					  array(10) {
        						["id"]=>
        						string(26) "offer_8083a5b....."
        						["name"]=>
        						string(39) "woo_91_73da6....."
        						["amount"]=>
        						int(100)
        						["currency"]=>
        						string(3) "EUR"
        						["interval"]=>
        						string(5) "1 DAY"
        						["trial_period_days"]=>
        						int(0)
        						["created_at"]=>
        						int(1389547028)
        						["updated_at"]=>
        						int(1389547028)
        						["subscription_count"]=>
        						array(2) {
        						  ["active"]=>
        						  string(1) "1"
        						  ["inactive"]=>
        						  string(1) "1"
        						}
        						["app_id"]=>
        						NULL
        					  }
        					  ["livemode"]=>
        					  bool(false)
        					  ["cancel_at_period_end"]=>
        					  bool(false)
        					  ["trial_start"]=>
        					  NULL
        					  ["trial_end"]=>
        					  NULL
        					  ["next_capture_at"]=>
        					  int(1389836717)
        					  ["created_at"]=>
        					  int(1389663382)
        					  ["updated_at"]=>
        					  int(1389750317)
        					  ["canceled_at"]=>
        					  NULL
        					  ["app_id"]=>
        					  NULL
        					  ["payment"]=>
        					  array(12) {
        						["id"]=>
        						string(28) "pay_4e3759f....."
        						["type"]=>
        						string(10) "creditcard"
        						["client"]=>
        						string(27) "client_dbe164....."
        						["card_type"]=>
        						string(4) "visa"
        						["country"]=>
        						NULL
        						["expire_month"]=>
        						string(2) "12"
        						["expire_year"]=>
        						string(4) "2020"
        						["card_holder"]=>
        						string(13) "dfgdfgdfgdfgd"
        						["last4"]=>
        						string(4) "1111"
        						["created_at"]=>
        						int(1389663369)
        						["updated_at"]=>
        						int(1389663380)
        						["app_id"]=>
        						NULL
        					  }
        					  ["client"]=>
        					  array(8) {
        						["id"]=>
        						string(27) "client_dbe164....."
        						["email"]=>
        						string(22) "*****@*****.**"
        						["description"]=>
        						string(15) "Matthias Reuter"
        						["created_at"]=>
        						int(1389547027)
        						["updated_at"]=>
        						int(1389547027)
        						["app_id"]=>
        						NULL
        						["payment"]=>
        						array(2) {
        						  [0]=>
        						  array(12) {
        							["id"]=>
        							string(28) "pay_1a5ff8....."
        							["type"]=>
        							string(10) "creditcard"
        							["client"]=>
        							string(27) "client_dbe16....."
        							["card_type"]=>
        							string(4) "visa"
        							["country"]=>
        							NULL
        							["expire_month"]=>
        							string(2) "12"
        							["expire_year"]=>
        							string(4) "2020"
        							["card_holder"]=>
        							string(10) "dfgdfgdfgd"
        							["last4"]=>
        							string(4) "1111"
        							["created_at"]=>
        							int(1389547027)
        							["updated_at"]=>
        							int(1389547028)
        							["app_id"]=>
        							NULL
        						  }
        						  [1]=>
        						  array(12) {
        							["id"]=>
        							string(28) "pay_4e375....."
        							["type"]=>
        							string(10) "creditcard"
        							["client"]=>
        							string(27) "client_dbe164....."
        							["card_type"]=>
        							string(4) "visa"
        							["country"]=>
        							NULL
        							["expire_month"]=>
        							string(2) "12"
        							["expire_year"]=>
        							string(4) "2020"
        							["card_holder"]=>
        							string(13) "dfgdfgdfgdfgd"
        							["last4"]=>
        							string(4) "1111"
        							["created_at"]=>
        							int(1389663369)
        							["updated_at"]=>
        							int(1389663380)
        							["app_id"]=>
        							NULL
        						  }
        						}
        						["subscription"]=>
        						array(2) {
        						  [0]=>
        						  string(24) "sub_fcc4....."
        						  [1]=>
        						  string(24) "sub_b71a....."
        						}
        					  }
        					}
        					["created_at"]=>
        					int(1389816435)
        					["app_id"]=>
        					NULL
        				  }
        				}
        				
        			*/
        //error_log(var_export($event_json,true)."\n\n", 3, PAYMILL_DIR.'lib/debug/PHP_errors.log');
        // get subscription info, if available
        if (isset($paymill_sub_id) && strlen($paymill_sub_id) > 0) {
            $sql = $wpdb->prepare('SELECT * FROM ' . $wpdb->prefix . 'paymill_subscriptions WHERE paymill_sub_id=%s', array($paymill_sub_id));
            $sub_cache = $wpdb->get_results($sql, ARRAY_A);
            $sub_cache = $sub_cache[0];
            /* output example:
            			SELECT * FROM wp_paymill_subscriptions WHERE paymill_sub_id="sub_b71adbf5e097bbe5ba80"
            			*/
            error_log("\n\n" . $sql . "\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
            /* output example:
            			
            			1
            			
            			30
            			
            			*/
            //error_log($sub_cache['woo_user_id']."\n\n".$sub_cache['woo_offer_id']."\n\n", 3, PAYMILL_DIR.'lib/debug/PHP_errors.log');
            $subscription = WC_Subscriptions_Manager::get_subscription($sub_cache['woo_offer_id']);
            // update subscriptions when webhook is triggered
            if (isset($sub_cache['woo_offer_id']) && strlen($sub_cache['woo_offer_id']) > 0) {
                // subscription successfully created
                if ($event_json['event']['event_type'] == 'subscription.created') {
                }
                // tell WooCommerce when payment for subscription is successfully processed
                if ($event_json['event']['event_type'] == 'subscription.succeeded') {
                    /* example data WC_Subscriptions_Manager::get_subscription:
                    				array(15) {
                    				  ["order_id"]=>
                    				  string(3) "201"
                    				  ["product_id"]=>
                    				  string(2) "91"
                    				  ["variation_id"]=>
                    				  string(0) ""
                    				  ["status"]=>
                    				  string(6) "active"
                    				  ["period"]=>
                    				  string(3) "day"
                    				  ["interval"]=>
                    				  string(1) "1"
                    				  ["length"]=>
                    				  string(2) "12"
                    				  ["start_date"]=>
                    				  string(19) "2014-01-12 17:17:10"
                    				  ["expiry_date"]=>
                    				  string(19) "2014-01-24 17:17:10"
                    				  ["end_date"]=>
                    				  string(1) "0"
                    				  ["trial_expiry_date"]=>
                    				  string(1) "0"
                    				  ["failed_payments"]=>
                    				  string(1) "0"
                    				  ["completed_payments"]=>
                    				  array(1) {
                    					[0]=>
                    					string(19) "2014-01-12 17:17:10"
                    				  }
                    				  ["suspension_count"]=>
                    				  string(1) "0"
                    				  ["last_payment_date"]=>
                    				  string(19) "2014-01-12 17:17:10"
                    				}
                    			*/
                    error_log(var_export($subscription, true) . "\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
                    // prevent multiple subscription renewals because of multiple webhook attempts.
                    $whole_period = 0;
                    switch ($subscription['period']) {
                        case 'day':
                        default:
                            $whole_period = intval($subscription['interval']) * 86400;
                            break;
                        case 'week':
                            $whole_period = intval($subscription['interval']) * 604800;
                            break;
                        case 'month':
                            $whole_period = intval($subscription['interval']) * 2160000;
                            // using 25 days to prevent problems with shorter months
                            break;
                        case 'year':
                            $whole_period = intval($subscription['interval']) * 30240000;
                            // using 350 days to prevent any timezone problems whatsoever
                            break;
                    }
                    if (count($subscription['completed_payments']) >= 1) {
                        if (strtotime(date(DATE_RFC822)) > strtotime($subscription['last_payment_date']) + $whole_period - 18000) {
                            // minus 5 hours to prevent any problems with pending triggers
                            $order = new WC_Order($subscription['order_id']);
                            //WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $subscription['product_id']);
                            WC_Subscriptions_Manager::process_subscription_payments_on_order($order);
                        }
                    } else {
                        $order = new WC_Order($subscription['order_id']);
                        $order->payment_complete();
                        WC_Subscriptions_Manager::activate_subscriptions_for_order($subscription['order_id']);
                    }
                    WC_Subscriptions_Manager::set_next_payment_date($sub_cache['woo_offer_id'], $order->customer_user);
                }
                // cancel subscription, as it was deleted through Paymill dashboard
                if ($event_json['event']['event_type'] == 'subscription.deleted') {
                    $sql = $wpdb->prepare('DELETE FROM ' . $wpdb->prefix . 'paymill_subscriptions WHERE woo_user_id=%s AND woo_offer_id=%s', array($sub_cache['woo_user_id'], $sub_cache['woo_offer_id']));
                    $wpdb->query($sql);
                    error_log("\n\n" . $sql . "\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
                    //WC_Subscriptions_Manager::cancel_subscriptions_for_order( $order );
                    WC_Subscriptions_Manager::cancel_subscription($sub_cache['woo_user_id'], $sub_cache['woo_offer_id']);
                }
                // tell WC that payment failure occured
                if ($event_json['event']['event_type'] == 'subscription.failed') {
                    WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($subscription['order_id'], $subscription['product_id']);
                }
            }
        }
        error_log(date(DATE_RFC822) . ' - Webhook ' . $event_json['event']['event_type'] . ' finished - end processing' . "\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
        error_log("\n\n########################################################################################################################\n\n", 3, PAYMILL_DIR . 'lib/debug/PHP_errors.log');
    }
}
 /**
  * After payment is completed on an order for switching a subscription, complete the switch.
  *
  * @param WC_Order|int $order A WC_Order object or ID of a WC_Order order.
  * @since 1.4
  */
 public static function maybe_complete_switch($order_id)
 {
     $original_subscription_key = get_post_meta($order_id, '_switched_subscription_key', true);
     if (!empty($original_subscription_key)) {
         $original_subscription = WC_Subscriptions_Manager::get_subscription($original_subscription_key);
         $original_order = new WC_Order($original_subscription['order_id']);
         if ('switched' !== $original_subscription['status']) {
             // Don't send "Cancelled Subscription" email to admins
             remove_action('cancelled_subscription', 'WC_Subscriptions_Email::send_subscription_email', 10, 2);
             // Cancel the existing subscription
             WC_Subscriptions_Manager::cancel_subscription($original_order->customer_user, $original_subscription_key);
             add_action('cancelled_subscription', 'WC_Subscriptions_Email::send_subscription_email', 10, 2);
             // Now set a custom status of "switched"
             $original_subscription['status'] = 'switched';
             WC_Subscriptions_Manager::update_subscription($original_subscription_key, $original_subscription);
             wp_clear_scheduled_hook('scheduled_subscription_end_of_prepaid_term', array('user_id' => (int) $original_order->customer_user, 'subscription_key' => $original_subscription_key));
         }
     }
 }
 /**
  * When an order is added or updated from the admin interface, check if a subscription product
  * has been manually added to the order or the details of the subscription have been modified,
  * and create/update the subscription as required.
  *
  * Save subscription order meta items
  *
  * @param int $post_id The ID of the post which is the WC_Order object.
  * @param Object $post The post object of the order.
  * @since 1.1
  */
 public static function pre_process_shop_order_meta($post_id, $post)
 {
     global $woocommerce, $wpdb;
     $order_contains_subscription = false;
     $order = new WC_Order($post_id);
     $existing_product_ids = array();
     foreach ($order->get_items() as $existing_item) {
         $existing_product_ids[] = self::get_items_product_id($existing_item);
     }
     $product_ids = array();
     if (isset($_POST['order_item_id'])) {
         foreach ($_POST['order_item_id'] as $order_item_id) {
             $product_ids[$order_item_id] = woocommerce_get_order_item_meta($order_item_id, '_product_id');
         }
     }
     // Check if there are new subscription products to be added, or the order already has a subscription item
     foreach (array_merge($product_ids, $existing_product_ids) as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's a subscription product, we have a subscription
         if (!$is_existing_item && WC_Subscriptions_Product::is_subscription($product_id)) {
             $order_contains_subscription = true;
         }
         // If this is an existing item and it's a subscription item, we have a subscription
         if ($is_existing_item && self::is_item_subscription($order, $product_id)) {
             $order_contains_subscription = true;
         }
     }
     if (!$order_contains_subscription) {
         return $post_id;
     }
     $existing_payment_method = get_post_meta($post_id, '_recurring_payment_method', true);
     $chosen_payment_method = isset($_POST['_recurring_payment_method']) ? stripslashes($_POST['_recurring_payment_method']) : '';
     // For subscriptions manually added using paypal, make sure the _paypal_first_ipn_ignored_for_pdt is set so that IPN notifications are never ignored
     if (isset($_POST['_payment_method']) && 'paypal' == $_POST['_payment_method'] && 'true' != get_post_meta($post_id, '_paypal_first_ipn_ignored_for_pdt', true)) {
         update_post_meta($post_id, '_paypal_first_ipn_ignored_for_pdt', 'true');
     }
     // If the recurring payment method is changing, or it isn't set make sure we have correct manual payment flag set
     if (isset($_POST['_recurring_payment_method']) || empty($existing_payment_method) && ($chosen_payment_method != $existing_payment_method || empty($chosen_payment_method))) {
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         // Make sure the subscription is cancelled with the current gateway
         if (!empty($existing_payment_method) && isset($payment_gateways[$existing_payment_method]) && $payment_gateways[$existing_payment_method]->supports('subscriptions')) {
             foreach ($product_ids as $product_id) {
                 WC_Subscriptions_Payment_Gateways::trigger_gateway_cancelled_subscription_hook(absint($_POST['customer_user']), WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id));
             }
         }
         if (!empty($chosen_payment_method) && isset($payment_gateways[$chosen_payment_method]) && $payment_gateways[$chosen_payment_method]->supports('subscriptions')) {
             $manual_renewal = 'false';
         } else {
             $manual_renewal = 'true';
         }
         update_post_meta($post_id, '_wcs_requires_manual_renewal', $manual_renewal);
         if (!empty($chosen_payment_method)) {
             update_post_meta($post_id, '_recurring_payment_method', stripslashes($_POST['_recurring_payment_method']));
         }
     }
     // Make sure the recurring order totals are correct
     update_post_meta($post_id, '_order_recurring_discount_total', WC_Subscriptions::format_total($_POST['_order_recurring_discount_total']));
     update_post_meta($post_id, '_order_recurring_total', WC_Subscriptions::format_total($_POST['_order_recurring_total']));
     // Update fields for WC < 2.1
     if (WC_Subscriptions::is_woocommerce_pre('2.1')) {
         // Also allow updates to the recurring payment method's title
         if (isset($_POST['_recurring_payment_method_title'])) {
             update_post_meta($post_id, '_recurring_payment_method_title', stripslashes($_POST['_recurring_payment_method_title']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_recurring_payment_method_title', '');
         }
         if (isset($_POST['_order_recurring_discount_cart'])) {
             update_post_meta($post_id, '_order_recurring_discount_cart', stripslashes($_POST['_order_recurring_discount_cart']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_discount_cart', 0);
         }
         if (isset($_POST['_order_recurring_tax_total'])) {
             // WC < 2.1
             update_post_meta($post_id, '_order_recurring_tax_total', stripslashes($_POST['_order_recurring_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_tax_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', stripslashes($_POST['_order_recurring_shipping_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_total', stripslashes($_POST['_order_recurring_shipping_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_total', 0);
         }
     }
     // Save tax rows
     $total_tax = 0;
     $total_shipping_tax = 0;
     if (isset($_POST['recurring_order_taxes_id'])) {
         // WC 2.0+
         $tax_keys = array('recurring_order_taxes_id', 'recurring_order_taxes_rate_id', 'recurring_order_taxes_amount', 'recurring_order_taxes_shipping_amount');
         foreach ($tax_keys as $tax_key) {
             ${$tax_key} = isset($_POST[$tax_key]) ? $_POST[$tax_key] : array();
         }
         foreach ($recurring_order_taxes_id as $item_id => $value) {
             $item_id = absint($item_id);
             $rate_id = absint($recurring_order_taxes_rate_id[$item_id]);
             if ($rate_id) {
                 $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                 $label = $rate->tax_rate_name ? $rate->tax_rate_name : $woocommerce->countries->tax_or_vat();
                 $compound = $rate->tax_rate_compound ? 1 : 0;
                 $code = array();
                 $code[] = $rate->tax_rate_country;
                 $code[] = $rate->tax_rate_state;
                 $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                 $code[] = absint($rate->tax_rate_priority);
                 $code = strtoupper(implode('-', array_filter($code)));
             } else {
                 $code = '';
                 $label = $woocommerce->countries->tax_or_vat();
             }
             $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => woocommerce_clean($code)), array('order_item_id' => $item_id), array('%s'), array('%d'));
             woocommerce_update_order_item_meta($item_id, 'rate_id', $rate_id);
             woocommerce_update_order_item_meta($item_id, 'label', $label);
             woocommerce_update_order_item_meta($item_id, 'compound', $compound);
             if (isset($recurring_order_taxes_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'tax_amount', WC_Subscriptions::format_total($recurring_order_taxes_amount[$item_id]));
                 $total_tax += WC_Subscriptions::format_total($recurring_order_taxes_amount[$item_id]);
             }
             if (isset($recurring_order_taxes_shipping_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'shipping_tax_amount', WC_Subscriptions::format_total($recurring_order_taxes_shipping_amount[$item_id]));
                 $total_shipping_tax += WC_Subscriptions::format_total($recurring_order_taxes_shipping_amount[$item_id]);
             }
         }
     }
     if (!isset($_POST['_order_recurring_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_tax_total', wc_round_tax_total($total_tax));
     }
     if (!isset($_POST['_order_recurring_shipping_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_tax_total', wc_round_tax_total($total_shipping_tax));
     }
     // And that shipping methods are updated as required
     if (isset($_POST['_recurring_shipping_method']) || isset($_POST['_recurring_shipping_method_title'])) {
         // WC < 2.1
         update_post_meta($post_id, '_recurring_shipping_method', stripslashes($_POST['_recurring_shipping_method']));
         update_post_meta($post_id, '_recurring_shipping_method_title', stripslashes($_POST['_recurring_shipping_method_title']));
     }
     // Shipping Rows
     $recurring_order_shipping = 0;
     if (isset($_POST['recurring_shipping_method_id'])) {
         // WC 2.1+
         $get_values = array('recurring_shipping_method_id', 'recurring_shipping_method_title', 'recurring_shipping_method', 'recurring_shipping_cost');
         foreach ($get_values as $value) {
             ${$value} = isset($_POST[$value]) ? $_POST[$value] : array();
         }
         foreach ($recurring_shipping_method_id as $item_id => $value) {
             if ('new' == $item_id) {
                 foreach ($value as $new_key => $new_value) {
                     $method_id = woocommerce_clean($recurring_shipping_method[$item_id][$new_key]);
                     $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id][$new_key]);
                     $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id][$new_key]);
                     $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                     if ($new_id) {
                         woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                         woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                     }
                     $recurring_order_shipping += $cost;
                 }
             } elseif ('old' == $item_id) {
                 // Migrate a WC 2.0.n shipping method to WC 2.1 format
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                 if ($new_id) {
                     woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                     woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                 }
                 $recurring_order_shipping += $cost;
                 delete_post_meta($post_id, '_recurring_shipping_method');
                 delete_post_meta($post_id, '_recurring_shipping_method_title');
             } else {
                 $item_id = absint($item_id);
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => $method_title), array('order_item_id' => $item_id), array('%s'), array('%d'));
                 woocommerce_update_order_item_meta($item_id, 'method_id', $method_id);
                 woocommerce_update_order_item_meta($item_id, 'cost', $cost);
                 $recurring_order_shipping += $cost;
             }
         }
     }
     if (!isset($_POST['_order_recurring_shipping_total'])) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_total', $recurring_order_shipping);
     }
     // Check if all the subscription products on the order have associated subscriptions on the user's account, and if not, add a new one
     foreach ($product_ids as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's not a subscription product, ignore it
         if (!$is_existing_item && !WC_Subscriptions_Product::is_subscription($product_id)) {
             continue;
         }
         // If this is an existing item and it's not a subscription, ignore it
         if ($is_existing_item && !self::is_item_subscription($order, $product_id)) {
             continue;
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id);
         $subscription = array();
         if (!empty($order->customer_user) && $_POST['customer_user'] != $order->customer_user) {
             $customer_has_changed = true;
             $hook_args = array('user_id' => (int) $order->customer_user, 'subscription_key' => $subscription_key);
             wc_unschedule_action('scheduled_subscription_trial_end', $hook_args);
             wc_unschedule_action('scheduled_subscription_payment', $hook_args);
             wc_unschedule_action('scheduled_subscription_expiration', $hook_args);
         } else {
             $customer_has_changed = false;
         }
         // In case it's a new order or the customer has changed
         $order->customer_user = $order->user_id = (int) $_POST['customer_user'];
         $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
         if (empty($subscription)) {
             // Add a new subscription
             // The order may not exist yet, so we need to set a few things ourselves
             if (empty($order->order_key)) {
                 $order->order_key = uniqid('order_');
                 add_post_meta($post_id, '_order_key', $order->order_key, true);
             }
             if (empty($_POST['order_date'])) {
                 $start_date = gmdate('Y-m-d H:i:s');
             } else {
                 $start_date = get_gmt_from_date($_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00');
             }
             WC_Subscriptions_Manager::create_pending_subscription_for_order($order, $product_id, array('start_date' => $start_date));
             // Add the subscription meta for this item to the order
             $functions_and_meta = array('get_period' => '_order_subscription_periods', 'get_interval' => '_order_subscription_intervals', 'get_length' => '_order_subscription_lengths');
             foreach ($functions_and_meta as $function_name => $meta_key) {
                 $subscription_meta = self::get_meta($order, $meta_key, array());
                 $subscription_meta[$product_id] = WC_Subscriptions_Product::$function_name($product_id);
                 update_post_meta($order->id, $meta_key, $subscription_meta);
             }
             // This works because meta is added when the item is added via Ajax
             self::process_shop_order_item_meta($post_id, $post);
             // If the order's existing status is something other than pending and the order status is not being changed, manually set the subscription's status (otherwise, it will be handled when WC transitions the order's status)
             if ($order->status == $_POST['order_status'] && 'pending' != $order->status) {
                 switch ($order->status) {
                     case 'completed':
                     case 'processing':
                         WC_Subscriptions_Manager::activate_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'cancelled':
                         WC_Subscriptions_Manager::cancel_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'failed':
                         WC_Subscriptions_Manager::failed_subscription_signup($order->customer_user, $subscription_key);
                         break;
                 }
             }
         }
     }
     // Determine whether we need to update any subscription dates for existing subscriptions (before the item meta is updated)
     if (!empty($product_ids)) {
         $start_date = $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . date(':s', strtotime($order->order_date));
         // Order's customer or start date changed for an existing order
         if ($customer_has_changed || !empty($order->order_date) && $order->order_date != $start_date) {
             self::$requires_update['expiration_date'] = array_values($product_ids);
             self::$requires_update['trial_expiration'] = array_values($product_ids);
             self::$requires_update['next_billing_date'] = array_values($product_ids);
         } elseif (isset($_POST['meta_key'])) {
             $item_meta_keys = isset($_POST['meta_key']) ? $_POST['meta_key'] : array();
             $new_meta_values = isset($_POST['meta_value']) ? $_POST['meta_value'] : array();
             foreach ($item_meta_keys as $item_meta_id => $meta_key) {
                 $meta_data = self::get_item_meta_data($item_meta_id);
                 $product_id = woocommerce_get_order_item_meta($meta_data->order_item_id, '_product_id');
                 // Set flags to update payment dates if required
                 switch ($meta_key) {
                     case '_subscription_period':
                     case '_subscription_interval':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_start_date':
                     case '_subscription_trial_length':
                     case '_subscription_trial_period':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['trial_expiration'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_length':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_trial_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['trial_expiration'][] = $product_id;
                         }
                         break;
                     case '_subscription_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                         }
                         break;
                 }
             }
         }
     }
 }
 /**
  * Handle activate & cancel actions for both individual items and bulk edit. 
  *
  * @since 1.0
  */
 public function process_actions()
 {
     if ($this->current_action() === false) {
         return;
     }
     $messages = array();
     $error_messages = array();
     // Single subscription action
     if (isset($_GET['subscription'])) {
         if (!wp_verify_nonce($_REQUEST['_wpnonce'], $_GET['subscription'])) {
             wp_die(__('Action failed. Invalid Nonce.', WC_Subscriptions::$text_domain));
         }
         if (!WC_Subscriptions_Manager::can_subscription_be_changed_to($_GET['new_status'], $_GET['subscription'], $_GET['user'])) {
             $error_messages[] = sprintf(__('Error: Subscription status can not be changed to "%s".', WC_Subscriptions::$text_domain), esc_html($_GET['new_status']));
         } else {
             switch ($_GET['new_status']) {
                 case 'active':
                     WC_Subscriptions_Manager::reactivate_subscription($_GET['user'], $_GET['subscription']);
                     $messages[] = __('Subscription activated.', WC_Subscriptions::$text_domain);
                     break;
                 case 'suspended':
                     WC_Subscriptions_Manager::suspend_subscription($_GET['user'], $_GET['subscription']);
                     $messages[] = __('Subscription suspended.', WC_Subscriptions::$text_domain);
                     break;
                 case 'cancelled':
                     WC_Subscriptions_Manager::cancel_subscription($_GET['user'], $_GET['subscription']);
                     $messages[] = __('Subscription cancelled.', WC_Subscriptions::$text_domain);
                     break;
                 case 'trash':
                     WC_Subscriptions_Manager::trash_subscription($_GET['user'], $_GET['subscription']);
                     $messages[] = __('Subscription trashed.', WC_Subscriptions::$text_domain);
                     break;
                 default:
                     $error_messages[] = __('Error: Unknown subscription status.', WC_Subscriptions::$text_domain);
                     break;
             }
         }
     } else {
         if (isset($_GET['subscriptions'])) {
             // Bulk actions
             if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'bulk-' . $this->_args['plural'])) {
                 wp_die(__('Bulk edit failed. Invalid Nonce.', WC_Subscriptions::$text_domain));
             }
             $subscriptions = $_GET[$this->_args['plural']];
             $subscription_count = 0;
             $error_count = 0;
             if ('trash' === $this->current_action()) {
                 foreach ($subscriptions as $user_id => $subscription_keys) {
                     foreach ($subscription_keys as $subscription_key) {
                         if (!WC_Subscriptions_Manager::can_subscription_be_changed_to('trash', $subscription_key, $user_id)) {
                             $error_count++;
                         } else {
                             $subscription_count++;
                             WC_Subscriptions_Manager::trash_subscription($user_id, $subscription_key);
                         }
                     }
                 }
                 if ($subscription_count > 0) {
                     $messages[] = sprintf(_n('%d subscription moved to trash.', '%s subscriptions moved to trash.', $subscription_count), $subscription_count);
                 }
                 if ($error_count > 0) {
                     $error_messages[] = sprintf(_n('%d subscription could not be trashed - is it active or suspended? Try cancelling it before trashing it.', '%s subscriptions could not be trashed - are they active or suspended? Try cancelling them before trashing.', $error_count), $error_count);
                 }
             }
         }
     }
     $status = isset($_GET['status']) ? $_GET['status'] : 'all';
     $message_nonce = wp_create_nonce(__FILE__);
     set_transient($this->message_transient_prefix . $message_nonce, array('messages' => $messages, 'error_messages' => $error_messages), 60 * 60);
     $redirect_to = add_query_arg(array('status' => $status, 'message' => $message_nonce), admin_url('admin.php?page=subscriptions'));
     // Redirect to avoid performning actions on a page refresh
     wp_safe_redirect($redirect_to);
 }
Пример #7
0
 /**
  * When an order is added or updated from the admin interface, check if a subscription product
  * has been manually added to the order or the details of the subscription have been modified, 
  * and create/update the subscription as required.
  *
  * Save subscription order meta items
  *
  * @param $post_id int The ID of the post which is the WC_Order object.
  * @param $post Object The post object of the order.
  * @since 1.1
  */
 public static function pre_process_shop_order_meta($post_id, $post)
 {
     global $woocommerce, $wpdb;
     $order_contains_subscription = false;
     $order = new WC_Order($post_id);
     $existing_product_ids = array();
     foreach ($order->get_items() as $existing_item) {
         $existing_product_ids[] = self::get_items_product_id($existing_item);
     }
     $product_ids = array();
     // WC <> 2.0 compatible posted product IDs
     if (isset($_POST['order_item_id'])) {
         foreach ($_POST['order_item_id'] as $order_item_id) {
             // WC 2.0+ has unique order item IDs and the product ID is a piece of meta
             $product_ids[$order_item_id] = woocommerce_get_order_item_meta($order_item_id, '_product_id');
         }
     } elseif (isset($_POST['item_id'])) {
         $product_ids = $_POST['item_id'];
     }
     // WC 1.x treated order item IDs as product IDs
     // Check if there are new subscription products to be added, or the order already has a subscription item
     foreach (array_merge($product_ids, $existing_product_ids) as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's a subscription product, we have a subscription
         if (!$is_existing_item && WC_Subscriptions_Product::is_subscription($product_id)) {
             $order_contains_subscription = true;
         }
         // If this is an existing item and it's a subscription item, we have a subscription
         if ($is_existing_item && WC_Subscriptions_Order::is_item_subscription($order, $product_id)) {
             $order_contains_subscription = true;
         }
     }
     if (!$order_contains_subscription) {
         return $post_id;
     }
     // If the payment method is changing, make sure we have correct manual payment flag set
     $chosen_payment_method = stripslashes($_POST['_payment_method']);
     $existing_payment_method = get_post_meta($post_id, '_payment_method', true);
     if ($chosen_payment_method != $existing_payment_method || empty($chosen_payment_method)) {
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         if (isset($payment_gateways[$chosen_payment_method]) && $payment_gateways[$chosen_payment_method]->supports('subscriptions')) {
             $manual_renewal = 'false';
         } else {
             $manual_renewal = 'true';
         }
         update_post_meta($post_id, '_wcs_requires_manual_renewal', $manual_renewal);
     }
     // Make sure the recurring order totals are correct
     update_post_meta($post_id, '_order_recurring_discount_cart', stripslashes($_POST['_order_recurring_discount_cart']));
     update_post_meta($post_id, '_order_recurring_discount_total', stripslashes($_POST['_order_recurring_discount_total']));
     update_post_meta($post_id, '_order_recurring_tax_total', stripslashes($_POST['_order_recurring_tax_total']));
     update_post_meta($post_id, '_order_recurring_total', stripslashes($_POST['_order_recurring_total']));
     if (isset($_POST['recurring_order_taxes_id'])) {
         // WC 2.0+
         $tax_keys = array('recurring_order_taxes_id', 'recurring_order_taxes_rate_id', 'recurring_order_taxes_amount', 'recurring_order_taxes_shipping_amount');
         foreach ($tax_keys as $tax_key) {
             ${$tax_key} = isset($_POST[$tax_key]) ? $_POST[$tax_key] : array();
         }
         foreach ($recurring_order_taxes_id as $item_id) {
             $item_id = absint($item_id);
             $rate_id = absint($recurring_order_taxes_rate_id[$item_id]);
             if ($rate_id) {
                 $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                 $label = $rate->tax_rate_name ? $rate->tax_rate_name : $woocommerce->countries->tax_or_vat();
                 $compound = $rate->tax_rate_compound ? 1 : 0;
                 $code = array();
                 $code[] = $rate->tax_rate_country;
                 $code[] = $rate->tax_rate_state;
                 $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                 $code[] = absint($rate->tax_rate_priority);
                 $code = strtoupper(implode('-', array_filter($code)));
             } else {
                 $code = '';
                 $label = $woocommerce->countries->tax_or_vat();
             }
             $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => woocommerce_clean($code)), array('order_item_id' => $item_id), array('%s'), array('%d'));
             woocommerce_update_order_item_meta($item_id, 'rate_id', $rate_id);
             woocommerce_update_order_item_meta($item_id, 'label', $label);
             woocommerce_update_order_item_meta($item_id, 'compound', $compound);
             if (isset($recurring_order_taxes_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'tax_amount', woocommerce_clean($recurring_order_taxes_amount[$item_id]));
             }
             if (isset($recurring_order_taxes_shipping_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($recurring_order_taxes_shipping_amount[$item_id]));
             }
         }
     } else {
         // WC 1.x
         if (!isset($_POST['_order_recurring_taxes'])) {
             $_POST['_order_recurring_taxes'] = array();
         }
         foreach ($_POST['_order_recurring_taxes'] as $index => $tax_details) {
             if (!isset($tax_details['compound'])) {
                 $_POST['_order_recurring_taxes'][$index]['compound'] = 0;
             }
         }
         update_post_meta($post_id, '_order_recurring_taxes', $_POST['_order_recurring_taxes']);
     }
     // Check if all the subscription products on the order have associated subscriptions on the user's account, and if not, add a new one
     foreach ($product_ids as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's not a subscription product, ignore it
         if (!$is_existing_item && !WC_Subscriptions_Product::is_subscription($product_id)) {
             continue;
         }
         // If this is an existing item and it's not a subscription, ignore it
         if ($is_existing_item && !WC_Subscriptions_Order::is_item_subscription($order, $product_id)) {
             continue;
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id);
         $subscription = array();
         // If order customer changed, move the subscription from the old customer's account to the new customer
         if (!empty($order->customer_user) && $order->customer_user != (int) $_POST['customer_user']) {
             $subscription = WC_Subscriptions_Manager::remove_users_subscription($order->customer_user, $subscription_key);
             if (!empty($subscription)) {
                 $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions((int) $_POST['customer_user']);
                 $subscriptions[$subscription_key] = $subscription;
                 WC_Subscriptions_Manager::update_users_subscriptions((int) $_POST['customer_user'], $subscriptions);
             }
         }
         // In case it's a new order or the customer has changed
         $order->customer_user = $order->user_id = (int) $_POST['customer_user'];
         $subscription = WC_Subscriptions_Manager::get_users_subscription($order->customer_user, $subscription_key);
         if (empty($subscription)) {
             // Add a new subscription
             // The order may not exist yet, so we need to set a few things ourselves
             if (empty($order->order_key)) {
                 $order->order_key = uniqid('order_');
                 add_post_meta($post_id, '_order_key', $order->order_key, true);
             }
             if (empty($_POST['order_date'])) {
                 $start_date = gmdate('Y-m-d H:i:s');
             } else {
                 $start_date = get_gmt_from_date($_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00');
             }
             WC_Subscriptions_Manager::create_pending_subscription_for_order($order, $product_id, array('start_date' => $start_date));
             // Add the subscription meta for this item to the order
             $functions_and_meta = array('get_period' => '_order_subscription_periods', 'get_interval' => '_order_subscription_intervals', 'get_length' => '_order_subscription_lengths');
             foreach ($functions_and_meta as $function_name => $meta_key) {
                 $subscription_meta = self::get_meta($order, $meta_key, array());
                 $subscription_meta[$product_id] = WC_Subscriptions_Product::$function_name($product_id);
                 update_post_meta($order->id, $meta_key, $subscription_meta);
             }
             // This works because process_shop_order_item_meta saves item meta to workaround a WC 1.x bug and in WC 2.0+ meta is added when the item is added via Ajax
             self::process_shop_order_item_meta($post_id, $post);
             // If the order's existing status is something other than pending and the order status is not being changed, manually set the subscription's status (otherwise, it will be handled when WC transitions the order's status)
             if ($order->status == $_POST['order_status'] && 'pending' != $order->status) {
                 switch ($order->status) {
                     case 'completed':
                     case 'processing':
                         WC_Subscriptions_Manager::activate_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'refunded':
                     case 'cancelled':
                         WC_Subscriptions_Manager::cancel_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'failed':
                         WC_Subscriptions_Manager::failed_subscription_signup($order->customer_user, $subscription_key);
                         break;
                 }
             }
         }
     }
     // Determine whether we need to update any subscription dates for existing subscriptions (before the item meta is updated)
     if (!empty($product_ids)) {
         $start_date = $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00';
         // Start date changed for an existing order
         if (!empty($order->order_date) && $order->order_date != $start_date) {
             self::$requires_update['expiration_date'] = array_values($product_ids);
             self::$requires_update['trial_expiration'] = array_values($product_ids);
             self::$requires_update['next_billing_date'] = array_values($product_ids);
         } elseif (isset($_POST['meta_key'])) {
             // WC 2.0+
             $item_meta_keys = isset($_POST['meta_key']) ? $_POST['meta_key'] : array();
             $new_meta_values = isset($_POST['meta_value']) ? $_POST['meta_value'] : array();
             foreach ($item_meta_keys as $item_meta_id => $meta_key) {
                 $meta_data = self::get_item_meta_data($item_meta_id);
                 $product_id = woocommerce_get_order_item_meta($meta_data->order_item_id, '_product_id');
                 // Set flags to update payment dates if required
                 switch ($meta_key) {
                     case '_subscription_period':
                     case '_subscription_interval':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_trial_length':
                     case '_subscription_trial_period':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['trial_expiration'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_length':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                 }
             }
         } elseif (isset($_POST['meta_name'])) {
             // WC 1.x
             $item_meta_names = isset($_POST['meta_name']) ? $_POST['meta_name'] : '';
             $item_meta_values = isset($_POST['meta_value']) ? $_POST['meta_value'] : '';
             $item_id_count = count($item_ids);
             for ($i = 0; $i < $item_id_count; $i++) {
                 if (!isset($item_ids[$i]) || !$item_ids[$i]) {
                     continue;
                 } elseif (!in_array($item_ids[$i], $existing_product_ids)) {
                     // New subscriptions throw a false positive
                     continue;
                 }
                 // Meta
                 $item_meta = new WC_Order_Item_Meta();
                 if (isset($item_meta_names[$i]) && isset($item_meta_values[$i])) {
                     $meta_names = $item_meta_names[$i];
                     $meta_values = $item_meta_values[$i];
                     $meta_names_count = count($meta_names);
                     for ($ii = 0; $ii < $meta_names_count; $ii++) {
                         $meta_name = esc_attr($meta_names[$ii]);
                         $meta_value = esc_attr($meta_values[$ii]);
                         if (!isset($meta_name) || !isset($meta_value)) {
                             continue;
                         }
                         // Set flags to update payment dates if required
                         switch ($meta_name) {
                             case '_subscription_period':
                             case '_subscription_interval':
                                 if ($meta_value != self::get_item_meta($order, $meta_name, $item_ids[$i])) {
                                     self::$requires_update['next_billing_date'][] = $item_ids[$i];
                                 }
                                 break;
                             case '_subscription_trial_length':
                             case '_subscription_trial_period':
                                 if ($meta_value != self::get_item_meta($order, $meta_name, $item_ids[$i])) {
                                     self::$requires_update['expiration_date'][] = $item_ids[$i];
                                     self::$requires_update['trial_expiration'][] = $item_ids[$i];
                                     self::$requires_update['next_billing_date'][] = $item_ids[$i];
                                 }
                                 break;
                             case '_subscription_length':
                                 if ($meta_value != self::get_item_meta($order, $meta_name, $item_ids[$i])) {
                                     self::$requires_update['expiration_date'][] = $item_ids[$i];
                                     self::$requires_update['next_billing_date'][] = $item_ids[$i];
                                 }
                                 break;
                         }
                     }
                 }
             }
         }
     }
 }
Пример #8
0
 /**
  * Delete a stored billing method
  */
 function delete_payment_method($payment_method)
 {
     global $woocommerce;
     $user = wp_get_current_user();
     $customer_vault_ids = get_user_meta($user->ID, 'customer_vault_ids', true);
     $id = $customer_vault_ids[$payment_method];
     // If method is Single Billing, actually delete the record
     if (substr($id, 0, 1) !== '_') {
         $inspire_request = array('username' => $this->username, 'password' => $this->password, 'customer_vault' => 'delete_customer', 'customer_vault_id' => $id);
         $response = $this->post_and_get_response($inspire_request);
         if ($response['response'] != 1) {
             $woocommerce->add_error(__('Sorry, there was an error: ', 'woocommerce') . $response['responsetext']);
             $woocommerce->show_messages();
             return;
         }
     }
     $last_method = count($customer_vault_ids) - 1;
     // Update subscription references
     if (class_exists('WC_Subscriptions_Manager')) {
         foreach ((array) WC_Subscriptions_Manager::get_users_subscriptions($user->ID) as $subscription) {
             $subscription_payment_method = get_post_meta($subscription['order_id'], 'payment_method_number', true);
             // Cancel subscriptions that were purchased with the deleted method
             if ($subscription_payment_method == $payment_method) {
                 delete_post_meta($subscription['order_id'], 'payment_method_number');
                 WC_Subscriptions_Manager::cancel_subscription($user->ID, WC_Subscriptions_Manager::get_subscription_key($subscription['order_id']));
             } else {
                 if ($subscription_payment_method == $last_method && $subscription['status'] != 'cancelled') {
                     update_post_meta($subscription['order_id'], 'payment_method_number', $payment_method);
                 }
             }
         }
     }
     // Delete the reference by replacing it with the last method in the array
     if ($payment_method < $last_method) {
         $customer_vault_ids[$payment_method] = $customer_vault_ids[$last_method];
     }
     unset($customer_vault_ids[$last_method]);
     update_user_meta($user->ID, 'customer_vault_ids', $customer_vault_ids);
     $woocommerce->add_message(__('Successfully deleted your information!', 'woocommerce'));
     $woocommerce->show_messages();
 }