/** * Change the status of a subscription and show a notice to the * user to say when the next payment will now be made on. * * @since 1.0.0 * @access public * @static * @param $subscription * @param $order_id * @param $product_id * @uses WC_Subscriptions::add_notice */ public static function change_users_subscription($subscription, $order_id, $product_id) { $subscription = !is_object($subscription) ? wcs_get_subscription($subscription) : $subscription; $current_next_subscription_payment = WC_Subscriptions_Order::get_next_payment_date($order_id, $product_id, $from_date = ''); // Get the date of the current next subscription. $next_subscription_payment = WC_Subscriptions_Order::calculate_next_payment_date($order_id, $product_id, $type = 'mysql', $current_next_subscription_payment); WCSO_Subscriptions_Order::update_next_payment($order_id, $next_subscription_payment); // Update the next payment on the subscriptions order. $subscription->add_order_note(__('Subscription was skipped by the subscriber from their subscription page.', 'woocommerce-skip-one')); // translators: placeholder is next subscription payment WC_Subscriptions::add_notice(sprintf(__('You next payment subscription will now be on the %s.', 'woocommerce-skip-one'), $next_subscription_payment), 'success'); }
/** * When a subscription payment hook is fired, reschedule the hook to run again on the * time/date of the next payment (if any). * * WP-Cron's built in wp_schedule_event() function can not be used because the recurrence * must be a timestamp, which creates inaccurate schedules for month and year billing periods. * * @since 1.0 */ public static function reschedule_subscription_payment($user_id, $subscription_key) { $subscription = self::get_users_subscription($user_id, $subscription_key); // Don't reschedule for cancelled or expired subscriptions if (!in_array($subscription['status'], array('expired', 'cancelled', 'failed', 'suspended'))) { $next_billing_timestamp = strtotime(WC_Subscriptions_Order::get_next_payment_date($subscription['order_id'], $subscription['product_id'])); // If the next billing date is before the expiration date, reschedule the 'scheduled_subscription_payment' hook if ($subscription['expiry_date'] == 0 || $next_billing_timestamp < strtotime($subscription['expiry_date'])) { wp_schedule_single_event($next_billing_timestamp, 'scheduled_subscription_payment', array('user_id' => (int) $user_id, 'subscription_key' => $subscription_key)); do_action('rescheduled_subscription_payment', $user_id, $subscription_key); } } }
/** * If no sort order set, default to title. If no sort order, default to descending. * * @since 1.0 */ function sort_subscriptions($a, $b) { $order_by = !empty($_REQUEST['orderby']) ? $_REQUEST['orderby'] : 'start_date'; $order = !empty($_REQUEST['order']) ? $_REQUEST['order'] : 'desc'; switch ($order_by) { case 'product_name': $product_name_a = get_the_title($a['product_id']); $product_name_b = get_the_title($b['product_id']); $result = strcasecmp($product_name_a, $product_name_b); break; case 'user': $user_a = get_user_by('id', $a['user_id']); $user_b = get_user_by('id', $b['user_id']); $result = strcasecmp($user_a->display_name, $user_b->display_name); break; case 'expiry_date': if ($order == 'asc') { $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]); } else { $result = self::sort_with_zero_at_beginning($a[$order_by], $b[$order_by]); } break; case 'end_date': $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]); // Display subscriptions that have not ended at the end of the list break; case 'next_payment_date': $next_payment_a = $a['status'] != 'active' ? 0 : strtotime(WC_Subscriptions_Order::get_next_payment_date($a['order_id'], $a['product_id'])); $next_payment_b = $b['status'] != 'active' ? 0 : strtotime(WC_Subscriptions_Order::get_next_payment_date($b['order_id'], $b['product_id'])); $result = self::sort_with_zero_at_end($next_payment_a, $next_payment_b); // Display subscriptions with no future payments at the end break; case 'last_payment_date': $last_payment_a = empty($a['completed_payments']) ? 0 : strtotime(array_pop($a['completed_payments'])); $last_payment_b = empty($b['completed_payments']) ? 0 : strtotime(array_pop($b['completed_payments'])); $result = self::sort_with_zero_at_end($last_payment_a, $last_payment_b); // Display subscriptions with no compelted payments at the end break; case 'order_id': $result = strnatcmp($a[$order_by], $b[$order_by]); break; default: $result = strcmp($a[$order_by], $b[$order_by]); break; } return $order == 'asc' ? $result : -$result; // Send final sort direction to usort }
?> </time> <?php } ?> </td> <td class="subscription-next-payment"> <?php if ($subscription_details['status'] != 'active') { ?> - <?php } else { ?> <?php $next_payment_date = WC_Subscriptions_Order::get_next_payment_date($subscription_details['order_id'], $subscription_details['product_id']); ?> <time title="<?php echo esc_attr(strtotime($next_payment_date)); ?> "> <?php echo date_i18n(get_option('date_format'), strtotime($next_payment_date)); ?> </time> <?php } ?> </td> </tr> <?php
/** * Remove the user from the subscription product's related groups. * @param int $user_id * @param string $subscription_key */ public static function cancelled_subscription($user_id, $subscription_key) { // Instead of just doing: // self::subscription_expired( $user_id, $subscription_key ); // schedule it so that memberships will last as long as the member // has actually paid for. $subscription = WC_Subscriptions_Manager::get_users_subscription($user_id, $subscription_key); if (isset($subscription['product_id']) && isset($subscription['order_id'])) { $expire_timestamp = strtotime(WC_Subscriptions_Order::get_next_payment_date($subscription['order_id'], $subscription['product_id'])); wp_schedule_single_event($expire_timestamp, 'groups_ws_subscription_expired', array('user_id' => $user_id, 'subscription_key' => $subscription_key)); } }