/** * Gets all the active and inactive subscriptions for a user, as specified by $user_id * * @param int $user_id (optional) The id of the user whose subscriptions you want. Defaults to the currently logged in user. * @param array $order_ids (optional) An array of post_ids of WC_Order objects as a way to get only subscriptions for certain orders. Defaults to null, which will return subscriptions for all orders. * @since 1.0 */ public static function get_users_subscriptions($user_id = 0, $order_ids = array()) { _deprecated_function(__METHOD__, '2.0', 'wcs_get_users_subscriptions( $user_id )'); $subscriptions_in_old_format = array(); foreach (wcs_get_users_subscriptions($user_id) as $subscription) { $subscriptions_in_old_format[wcs_get_old_subscription_key($subscription)] = wcs_get_subscription_in_deprecated_structure($subscription); } return apply_filters('woocommerce_users_subscriptions', $subscriptions_in_old_format, $user_id); }
/** * Display a notice if functions are hooked to the old filter and apply the old filters args * * @since 2.0 */ protected function trigger_hook($old_hook, $new_callback_args) { if (0 === strpos($old_hook, 'admin_changed_subscription_to_')) { // New arg spec: $subscription_id // Old arg spec: $subscription_key $subscription = wcs_get_subscription($new_callback_args[0]); do_action($old_hook, wcs_get_old_subscription_key($subscription)); } elseif (0 === strpos($old_hook, 'scheduled_subscription_payment_')) { // New arg spec: $amount, $renewal_order // Old arg spec: $amount, $original_order, $product_id $subscription = $new_callback_args[0]; $subscriptions = wcs_get_subscriptions_for_renewal_order($new_callback_args[1]); if (!empty($subscriptions)) { $subscription = array_pop($subscriptions); do_action($old_hook, $new_callback_args[0], self::get_order($subscription), self::get_product_id($subscription)); } } elseif (0 === strpos($old_hook, 'activated_subscription_') || 0 === strpos($old_hook, 'reactivated_subscription_') || 0 === strpos($old_hook, 'subscription_put_on-hold_') || 0 === strpos($old_hook, 'cancelled_subscription_') || 0 === strpos($old_hook, 'subscription_expired_')) { // New arg spec: $subscription // Old arg spec: $order, $product_id $subscription = $new_callback_args[0]; do_action($old_hook, self::get_order($subscription), self::get_product_id($subscription)); } elseif (0 === strpos($old_hook, 'customer_changed_subscription_to_')) { // New arg spec: $subscription // Old arg spec: $subscription_key do_action($old_hook, wcs_get_old_subscription_key($new_callback_args[0])); } elseif (0 === strpos($old_hook, 'woocommerce_subscriptions_updated_recurring_payment_method_to_')) { // New arg spec: $subscription, $old_payment_method // Old arg spec: $order, $subscription_key, $old_payment_method $subscription = $new_callback_args[0]; $old_payment_method = $new_callback_args[2]; do_action($old_hook, self::get_order($subscription), wcs_get_old_subscription_key($subscription), $old_payment_method); } elseif (0 === strpos($old_hook, 'woocommerce_subscriptions_updated_recurring_payment_method_from_')) { // New arg spec: $subscription, $new_payment_method // Old arg spec: $order, $subscription_key, $new_payment_method $subscription = $new_callback_args[0]; $new_payment_method = $new_callback_args[1]; do_action($old_hook, self::get_order($subscription), wcs_get_old_subscription_key($subscription), $new_payment_method); } elseif (0 === strpos($old_hook, 'woocommerce_subscriptions_changed_failing_payment_method_')) { // New arg spec: $subscription, $renewal_order // Old arg spec: $original_order, $renewal_order, $subscription_key $subscription = $new_callback_args[0]; do_action($old_hook, self::get_order($subscription), $new_callback_args[1], wcs_get_old_subscription_key($subscription)); } }
/** * Trigger the old action with the original callback parameters * * @since 2.0 */ protected function trigger_hook($old_hook, $new_callback_args) { switch ($old_hook) { // New arg spec: $subscription_id // Old arg spec: $user_id, $subscription_key case 'scheduled_subscription_payment': case 'subscription_end_of_prepaid_term': case 'subscription_trial_end': $subscription = wcs_get_subscription($new_callback_args[0]); do_action($old_hook, $subscription->get_user_id(), wcs_get_old_subscription_key($subscription)); break; // New arg spec: $subscription // Old arg spec: $user_id, $subscription_key // New arg spec: $subscription // Old arg spec: $user_id, $subscription_key case 'processed_subscription_payment': case 'processed_subscription_renewal_payment': case 'processed_subscription_payment_failure': $subscription = $new_callback_args[0]; do_action($old_hook, $subscription->get_user_id(), wcs_get_old_subscription_key($subscription)); break; // New arg spec: $renewal_order, $subscription // Old arg spec: $subscription_key, $original_order // New arg spec: $renewal_order, $subscription // Old arg spec: $subscription_key, $original_order case 'woocommerce_subscriptions_processed_failed_renewal_order_payment': $renewal_order = $new_callback_args[0]; $subscription = $new_callback_args[1]; do_action($old_hook, wcs_get_old_subscription_key($subscription), self::get_order($subscription)); break; // New arg spec: $subscription, $new_payment_method, $old_payment_method // Old arg spec: $order, $subscription_key, $new_payment_method, $old_payment_method // New arg spec: $subscription, $new_payment_method, $old_payment_method // Old arg spec: $order, $subscription_key, $new_payment_method, $old_payment_method case 'woocommerce_subscriptions_pre_update_recurring_payment_method': case 'woocommerce_subscriptions_updated_recurring_payment_method': $subscription = $new_callback_args[0]; $new_payment_method = $new_callback_args[1]; $old_payment_method = $new_callback_args[2]; do_action($old_hook, self::get_order($subscription), wcs_get_old_subscription_key($subscription), $new_payment_method, $old_payment_method); break; // New arg spec: $subscription, $renewal_order // Old arg spec: $original_order, $renewal_order, $subscription_key // New arg spec: $subscription, $renewal_order // Old arg spec: $original_order, $renewal_order, $subscription_key case 'woocommerce_subscriptions_changed_failing_payment_method': $subscription = $new_callback_args[0]; $renewal_order = $new_callback_args[1]; do_action($old_hook, self::get_order($subscription), $renewal_order, wcs_get_old_subscription_key($subscription)); break; // New arg spec: $order // Old arg spec: $order // New arg spec: $order // Old arg spec: $order case 'subscriptions_suspended_for_order': do_action($old_hook, $new_callback_args[0]); break; // New arg spec: $subscription // Old arg spec: $subscription_key, $order // New arg spec: $subscription // Old arg spec: $subscription_key, $order case 'woocommerce_subscriptions_change_payment_method_via_pay_shortcode': $subscription = $new_callback_args[0]; do_action($old_hook, wcs_get_old_subscription_key($subscription), self::get_order($subscription)); break; // New arg spec: $subscription // Old arg spec: $user_id, $subscription_key // New arg spec: $subscription // Old arg spec: $user_id, $subscription_key case 'activated_subscription': case 'subscription_put_on-hold': case 'suspended_subscription': case 'cancelled_subscription': case 'reactivated_subscription': case 'subscription_expired': $subscription = $new_callback_args[0]; do_action($old_hook, $subscription->get_user_id(), wcs_get_old_subscription_key($subscription)); break; } }
/** * A general purpose function for grabbing an array of subscriptions in form of 'subscription_key' => 'subscription_details'. * * The $args param is based on the parameter of the same name used by the core WordPress @see get_posts() function. * It can be used to choose which subscriptions should be returned by the function, how many subscriptions should be returned * and in what order those subscriptions should be returned. * * @param array $args A set of name value pairs to determine the return value. * 'subscriptions_per_page' The number of subscriptions to return. Set to -1 for unlimited. Default 10. * 'offset' An optional number of subscription to displace or pass over. Default 0. * 'orderby' The field which the subscriptions should be ordered by. Can be 'start_date', 'expiry_date', 'end_date', 'status', 'name' or 'order_id'. Defaults to 'start_date'. * 'order' The order of the values returned. Can be 'ASC' or 'DESC'. Defaults to 'DESC' * 'customer_id' The user ID of a customer on the site. * 'product_id' The post ID of a WC_Product_Subscription, WC_Product_Variable_Subscription or WC_Product_Subscription_Variation object * 'subscription_status' Any valid subscription status. Can be 'any', 'active', 'cancelled', 'suspended', 'expired', 'pending' or 'trash'. Defaults to 'any'. * @return array Subscription details in 'subscription_key' => 'subscription_details' form. * @since 1.4 */ public static function get_subscriptions($args = array()) { if (isset($args['orderby'])) { // Although most of these weren't public orderby values, they were used internally so may have been used by developers switch ($args['orderby']) { case '_subscription_status': _deprecated_argument(__METHOD__, '2.0', 'The "_subscription_status" orderby value is deprecated. Use "status" instead.'); $args['orderby'] = 'status'; break; case '_subscription_start_date': _deprecated_argument(__METHOD__, '2.0', 'The "_subscription_start_date" orderby value is deprecated. Use "start_date" instead.'); $args['orderby'] = 'start_date'; break; case 'expiry_date': case '_subscription_expiry_date': case '_subscription_end_date': _deprecated_argument(__METHOD__, '2.0', 'The expiry date orderby value is deprecated. Use "end_date" instead.'); $args['orderby'] = 'end_date'; break; case 'trial_expiry_date': case '_subscription_trial_expiry_date': _deprecated_argument(__METHOD__, '2.0', 'The trial expiry date orderby value is deprecated. Use "trial_end_date" instead.'); $args['orderby'] = 'trial_end_date'; break; case 'name': _deprecated_argument(__METHOD__, '2.0', 'The "name" orderby value is deprecated - subscriptions no longer have just one name as they may contain multiple items.'); break; } } _deprecated_function(__METHOD__, '2.0', 'wcs_get_subscriptions( $args )'); $subscriptions = wcs_get_subscriptions($args); $subscriptions_in_deprecated_structure = array(); // Get the subscriptions in the backward compatible structure foreach ($subscriptions as $subscription) { $subscriptions_in_deprecated_structure[wcs_get_old_subscription_key($subscription)] = wcs_get_subscription_in_deprecated_structure($subscription); } return apply_filters('woocommerce_get_subscriptions', $subscriptions_in_deprecated_structure, $args); }
/** * Because the upgrader may have attempted to set an invalid end date on the subscription, it could * lead to the entire date update process failing, which would mean that a next payment date would * not be set even when one existed. * * This method checks if a given subscription has no next payment date, and if it doesn't, it checks * if one was previously scheduled for the old subscription. If one was, and that date is in the future, * it will pass that date back for being set on the subscription. If a date was scheduled but that is now * in the past, it will recalculate it. * * @param WC_Subscription $subscription the subscription to check * @return string|bool false if the date does not need to be repaired or the new date if it should be repaired */ protected static function check_next_payment_date($subscription) { global $wpdb; // the subscription doesn't have a next payment date set, let's see if it should if (0 == $subscription->get_time('next_payment') && $subscription->has_status('active')) { $old_hook_args = array('user_id' => (int) $subscription->get_user_id(), 'subscription_key' => wcs_get_old_subscription_key($subscription)); // get the latest scheduled subscription payment in v1.5 $old_next_payment_date = $wpdb->get_var($wpdb->prepare("SELECT post_date_gmt FROM {$wpdb->posts}\n\t\t\t\t WHERE post_type = %s\n\t\t\t\t AND post_content = %s\n\t\t\t\t AND post_title = 'scheduled_subscription_payment'\n\t\t\t\t ORDER BY post_date_gmt DESC", ActionScheduler_wpPostStore::POST_TYPE, wcs_json_encode($old_hook_args))); WCS_Upgrade_Logger::add(sprintf('For subscription %d: new next payment date = %s.', $subscription->id, var_export($subscription->get_date('next_payment'), true))); WCS_Upgrade_Logger::add(sprintf('For subscription %d: old next payment date = %s.', $subscription->id, var_export($old_next_payment_date, true))); // if we have a date, make sure it's valid if (null !== $old_next_payment_date) { if (strtotime($old_next_payment_date) <= gmdate('U')) { $repair_date = $subscription->calculate_date('next_payment'); if (0 == $repair_date) { $repair_date = false; } WCS_Upgrade_Logger::add(sprintf('For subscription %d: old next payment date is in the past, setting it to %s.', $subscription->id, var_export($repair_date, true))); } else { $repair_date = $old_next_payment_date; } } else { // let's just double check we shouldn't have a date set by recalculating it $calculated_next_payment_date = $subscription->calculate_date('next_payment'); if (0 != $calculated_next_payment_date && strtotime($calculated_next_payment_date) > gmdate('U')) { $repair_date = $calculated_next_payment_date; } else { $repair_date = false; } WCS_Upgrade_Logger::add(sprintf('For subscription %d: no old next payment date, setting it to %s.', $subscription->id, var_export($repair_date, true))); } } else { $repair_date = false; } WCS_Upgrade_Logger::add(sprintf('For subscription %d: repair next payment date = %s.', $subscription->id, var_export($repair_date, true))); return $repair_date; }
/** * Handle switched subscription (Subscriptions 2.x) * * @param WC_Subscription $subscription * @param unknown $new_order_item * @param unknown $switched_order_item */ public static function woocommerce_subscriptions_switched_item($subscription, $new_order_item, $switched_order_item) { $new_subscription_key = wcs_get_old_subscription_key($subscription); if (isset($switched_order_item['product_id']) && isset($switched_order_item['order_id'])) { $order_id = $switched_order_item['order_id']; // the subscription id $product_id = $switched_order_item['product_id']; $user_id = $subscription->get_user_id(); if ($switched_subscription = wcs_get_subscription($order_id)) { self::subscription_status_cancelled($switched_subscription); } } self::subscription_status_active($subscription); }
/** * Renders a table with subscription information. * @param array $options * @param int $n will be set to the number of subscriptions found */ public static function render($options, &$n) { global $wpdb; $output = ''; if (isset($options['user_id'])) { $user = new WP_User($options['user_id']); } else { return $output; } $statuses = array('active'); $show_all = false; if (isset($options['status'])) { $status = $options['status']; if (is_string($status)) { if (trim($status) === '*') { $statuses = array('active', 'on-hold', 'cancelled', 'trash', 'deleted', 'switched'); } else { $statuses = array(); $_statuses = explode(',', $status); foreach ($_statuses as $status) { $status = strtolower(trim($status)); switch ($status) { case 'active': case 'on-hold': case 'cancelled': case 'trash': case 'deleted': case 'switched': $statuses[] = $status; break; } } } } } $exclude_cancelled_after_end_of_prepaid_term = isset($options['exclude_cancelled_after_end_of_prepaid_term']) && ($options['exclude_cancelled_after_end_of_prepaid_term'] === true || $options['exclude_cancelled_after_end_of_prepaid_term'] == 'true' || $options['exclude_cancelled_after_end_of_prepaid_term'] == 'yes'); $include_cancelled_orders = isset($options['include_cancelled_orders']) && ($options['include_cancelled_orders'] === true || $options['include_cancelled_orders'] == 'true' || $options['include_cancelled_orders'] == 'yes'); $include_refunded_orders = isset($options['include_refunded_orders']) && ($options['include_refunded_orders'] === true || $options['include_refunded_orders'] == 'true' || $options['include_refunded_orders'] == 'yes'); if (function_exists('wcs_get_users_subscriptions')) { $results = array(); foreach (wcs_get_users_subscriptions($user->ID) as $subscription) { $results[wcs_get_old_subscription_key($subscription)] = wcs_get_subscription_in_deprecated_structure($subscription); } } else { $results = WC_Subscriptions_Manager::get_users_subscriptions($user->ID); } // pre-filter by status $_results = array(); foreach ($results as $result_key => $result) { $valid = false; if (in_array($result['status'], $statuses)) { $valid = true; } // exclude subscriptions from cancelled or refunded orders if (isset($result['order_id'])) { if ($order = Groups_WS_Helper::get_order($result['order_id'])) { switch ($order->status) { case 'cancelled': if (!$include_cancelled_orders) { $valid = false; } break; case 'refunded': if (!$include_refunded_orders) { $valid = false; } break; } } } if ($exclude_cancelled_after_end_of_prepaid_term && $result['status'] == 'cancelled') { $hook_args = array('user_id' => (int) $user->ID, 'subscription_key' => $result_key); $end_timestamp = wp_next_scheduled('scheduled_subscription_end_of_prepaid_term', $hook_args); if ($end_timestamp === false || $end_timestamp <= time()) { $valid = false; } } if ($valid) { $_results[$result_key] = $result; } } $results = $_results; $n = count($results); if ($n > 0) { $column_display_names = array('status' => __('Status', GROUPS_WS_PLUGIN_DOMAIN), 'title' => __('Subscription', GROUPS_WS_PLUGIN_DOMAIN), 'start_date' => __('Start Date', GROUPS_WS_PLUGIN_DOMAIN), 'expiry_date' => __('Expiration', GROUPS_WS_PLUGIN_DOMAIN), 'end_date' => __('End Date', GROUPS_WS_PLUGIN_DOMAIN), 'trial_expiry_date' => __('Trial Expiration', GROUPS_WS_PLUGIN_DOMAIN), 'groups' => __('Groups', GROUPS_WS_PLUGIN_DOMAIN), 'order_id' => __('Order', GROUPS_WS_PLUGIN_DOMAIN)); if (isset($options['columns']) && $options['columns'] !== null) { if (is_string($options['columns'])) { $columns = explode(',', $options['columns']); $_columns = array(); foreach ($columns as $column) { $_columns[] = trim($column); } $options['columns'] = $_columns; } $new_columns = array(); foreach ($options['columns'] as $key) { if (key_exists($key, $column_display_names)) { $new_columns[$key] = $column_display_names[$key]; } } $column_display_names = $new_columns; } if (count($column_display_names) > 0) { $output .= '<table class="subscriptions">'; $output .= '<thead>'; $output .= '<tr>'; foreach ($column_display_names as $key => $column_display_name) { $output .= "<th scope='col' class='{$key}'>{$column_display_name}</th>"; } $output .= '</tr>'; $output .= '</thead>'; $output .= '<tbody>'; $i = 0; foreach ($results as $result_key => $result) { $order = Groups_WS_Helper::get_order($result['order_id']); if ($order) { $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $result['product_id']); $product = $order->get_product_from_item($order_item); $output .= '<tr class="' . ($i % 2 == 0 ? 'even' : 'odd') . '">'; foreach ($column_display_names as $column_key => $column_title) { $output .= sprintf('<td class="%s">', $column_key); switch ($column_key) { case 'status': $output .= WC_Subscriptions_Manager::get_status_to_display($result['status'], $result_key, $user->ID); break; case 'title': $output .= WC_Subscriptions_Order::get_item_name($result['order_id'], $result['product_id']); if (isset($product->variation_data)) { $column_content .= '<br />'; if (function_exists('wc_get_formatted_variation')) { $column_content .= wc_get_formatted_variation($product->variation_data, true); } else { $column_content .= woocommerce_get_formatted_variation($product->variation_data, true); } } break; case 'start_date': case 'expiry_date': case 'end_date': if ($column_key == 'expiry_date' && $result[$column_key] == 0) { $output .= __('Never', GROUPS_WS_PLUGIN_DOMAIN); } else { if ($column_key == 'end_date' && $result[$column_key] == 0) { $output .= __('Not yet ended', GROUPS_WS_PLUGIN_DOMAIN); } else { $user_timestamp = strtotime($result[$column_key]) + get_option('gmt_offset') * 3600; $output .= sprintf('<time title="%s">%s</time>', esc_attr($user_timestamp), date_i18n(get_option('date_format'), $user_timestamp)); } } break; case 'trial_expiry_date': $trial_expiration = WC_Subscriptions_Manager::get_trial_expiration_date($result_key, $user->ID, 'timestamp'); if (empty($trial_expiration)) { $output .= '-'; } else { $trial_expiration = $trial_expiration + get_option('gmt_offset') * 3600; $output .= sprintf('<time title="%s">%s</time>', esc_attr($trial_expiration), date_i18n(get_option('date_format'), $trial_expiration)); } break; case 'groups': if ($product_groups = get_post_meta($result['product_id'], '_groups_groups', false)) { if (count($product_groups) > 0) { $output .= '<ul>'; foreach ($product_groups as $group_id) { if ($group = Groups_Group::read($group_id)) { $output .= '<li>' . wp_filter_nohtml_kses($group->name) . '</li>'; } } $output .= '</ul>'; } } break; case 'order_id': $output .= sprintf(__('Order %d', GROUPS_WS_PLUGIN_DOMAIN), $result['order_id']); break; } $output .= '</td>'; } $output .= '</tr>'; $i++; } } $output .= '</tbody>'; $output .= '</table>'; } } return $output; }