/** * A general purpose function for grabbing an array of subscriptions in form of post_id => WC_Subscription * * The $args parameter 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', 'trial_end_date', 'end_date', 'status' 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 * 'order_id' The post ID of a shop_order post/WC_Order object which was used to create the subscription * 'subscription_status' Any valid subscription status. Can be 'any', 'active', 'cancelled', 'suspended', 'expired', 'pending' or 'trash'. Defaults to 'any'. * @return array Subscription details in post_id => WC_Subscription form. * @since 2.0 */ function wcs_get_subscriptions($args) { global $wpdb; $args = wp_parse_args($args, array('subscriptions_per_page' => 10, 'paged' => 1, 'offset' => 0, 'orderby' => 'start_date', 'order' => 'DESC', 'customer_id' => 0, 'product_id' => 0, 'variation_id' => 0, 'order_id' => 0, 'subscription_status' => 'any', 'meta_query_relation' => 'AND')); // if order_id is not a shop_order if (0 !== $args['order_id'] && 'shop_order' !== get_post_type($args['order_id'])) { return array(); } // Make sure status starts with 'wc-' if (!in_array($args['subscription_status'], array('any', 'trash'))) { $args['subscription_status'] = wcs_sanitize_subscription_status_key($args['subscription_status']); } // Prepare the args for WP_Query $query_args = array('post_type' => 'shop_subscription', 'post_status' => $args['subscription_status'], 'posts_per_page' => $args['subscriptions_per_page'], 'paged' => $args['paged'], 'offset' => $args['offset'], 'order' => $args['order'], 'fields' => 'ids', 'meta_query' => array()); // Maybe only get subscriptions created by a certain order if (0 != $args['order_id'] && is_numeric($args['order_id'])) { $query_args['post_parent'] = $args['order_id']; } // Map subscription specific orderby values to internal/WordPress keys switch ($args['orderby']) { case 'status': $query_args['orderby'] = 'post_status'; break; case 'start_date': $query_args['orderby'] = 'date'; break; case 'trial_end_date': case 'end_date': // We need to orderby post meta value: http://www.paulund.co.uk/order-meta-query $query_args = array_merge($query_args, array('orderby' => 'meta_value', 'meta_key' => wcs_get_date_meta_key($args['orderby']), 'meta_type' => 'DATETIME')); $query_args['meta_query'][] = array('key' => wcs_get_date_meta_key($args['orderby']), 'value' => 'EXISTS', 'type' => 'DATETIME'); break; default: $query_args['orderby'] = $args['orderby']; break; } // Maybe filter to a specific user if (0 != $args['customer_id'] && is_numeric($args['customer_id'])) { $query_args['meta_query'][] = array('key' => '_customer_user', 'value' => $args['customer_id'], 'type' => 'numeric', 'compare' => is_array($args['customer_id']) ? 'IN' : '='); } // We need to restrict subscriptions to those which contain a certain product/variation if (0 != $args['product_id'] && is_numeric($args['product_id']) || 0 != $args['variation_id'] && is_numeric($args['variation_id'])) { $query_args['post__in'] = wcs_get_subscriptions_for_product(array($args['product_id'], $args['variation_id'])); } if (!empty($query_args['meta_query'])) { $query_args['meta_query']['relation'] = $args['meta_query_relation']; } $query_args = apply_filters('woocommerce_get_subscriptions_query_args', $query_args, $args); $subscription_post_ids = get_posts($query_args); $subscriptions = array(); foreach ($subscription_post_ids as $post_id) { $subscriptions[$post_id] = wcs_get_subscription($post_id); } return apply_filters('woocommerce_got_subscriptions', $subscriptions, $args); }
/** * Filters and sorting handler * * @param array $vars * @return array */ public function request_query($vars) { global $typenow; if ('shop_subscription' === $typenow) { // Filter the orders by the posted customer. if (isset($_GET['_customer_user']) && $_GET['_customer_user'] > 0) { $vars['meta_key'] = '_customer_user'; $vars['meta_value'] = (int) $_GET['_customer_user']; } if (isset($_GET['_wcs_product']) && $_GET['_wcs_product'] > 0) { $subscription_ids = wcs_get_subscriptions_for_product($_GET['_wcs_product']); if (!empty($subscription_ids)) { $vars['post__in'] = $subscription_ids; } else { // no subscriptions contain this product, but we need to pass post__in an ID that no post will have because WP returns all posts when post__in is an empty array: https://core.trac.wordpress.org/ticket/28099 $vars['post__in'] = array(0); } } // Sorting if (isset($vars['orderby'])) { switch ($vars['orderby']) { case 'order_total': $vars = array_merge($vars, array('meta_key' => '_order_total', 'orderby' => 'meta_value_num')); break; case 'last_payment_date': add_filter('posts_clauses', array($this, 'posts_clauses'), 10, 2); break; case 'trial_end_date': case 'next_payment_date': case 'end_date': $vars = array_merge($vars, array('meta_key' => sprintf('_schedule_%s', str_replace('_date', '', $vars['orderby'])), 'meta_type' => 'DATETIME', 'orderby' => 'meta_value')); break; } } // Status if (!isset($vars['post_status'])) { $vars['post_status'] = array_keys(wcs_get_subscription_statuses()); } } return $vars; }
/** * Filters and sorting handler * * @param array $vars * @return array */ public function request_query($vars) { global $typenow; if ('shop_subscription' === $typenow) { // Filter the orders by the posted customer. if (isset($_GET['_customer_user']) && $_GET['_customer_user'] > 0) { $vars['meta_query'][] = array('key' => '_customer_user', 'value' => (int) $_GET['_customer_user'], 'compare' => '='); } if (isset($_GET['_wcs_product']) && $_GET['_wcs_product'] > 0) { $subscription_ids = wcs_get_subscriptions_for_product($_GET['_wcs_product']); if (!empty($subscription_ids)) { $vars['post__in'] = $subscription_ids; } else { // no subscriptions contain this product, but we need to pass post__in an ID that no post will have because WP returns all posts when post__in is an empty array: https://core.trac.wordpress.org/ticket/28099 $vars['post__in'] = array(0); } } if (!empty($_GET['_payment_method'])) { $payment_gateway_filter = 'none' == $_GET['_payment_method'] ? '' : $_GET['_payment_method']; $query_vars = array('post_type' => 'shop_subscription', 'posts_per_page' => -1, 'post_status' => 'any', 'fields' => 'ids', 'meta_query' => array(array('key' => '_payment_method', 'value' => $payment_gateway_filter))); // If there are already set post restrictions (post__in) apply them to this query if (isset($vars['post__in'])) { $query_vars['post__in'] = $vars['post__in']; } $subscription_ids = get_posts($query_vars); if (!empty($subscription_ids)) { $vars['post__in'] = $subscription_ids; } else { $vars['post__in'] = array(0); } } // Sorting if (isset($vars['orderby'])) { switch ($vars['orderby']) { case 'order_total': $vars = array_merge($vars, array('meta_key' => '_order_total', 'orderby' => 'meta_value_num')); break; case 'last_payment_date': add_filter('posts_clauses', array($this, 'posts_clauses'), 10, 2); break; case 'trial_end_date': case 'next_payment_date': case 'end_date': $vars = array_merge($vars, array('meta_key' => sprintf('_schedule_%s', str_replace('_date', '', $vars['orderby'])), 'meta_type' => 'DATETIME', 'orderby' => 'meta_value')); break; } } // Status if (!isset($vars['post_status'])) { $vars['post_status'] = array_keys(wcs_get_subscription_statuses()); } } return $vars; }
/** * Grant downloadable file access to any newly added files on any existing subscriptions * which don't have existing permissions. * * @param int $product_id * @param int $variation_id * @param array $downloadable_files product downloadable files * @since 2.0.18 */ public static function grant_new_file_product_permissions($product_id, $variation_id, $downloadable_files) { global $wpdb; $product_id = $variation_id ? $variation_id : $product_id; $product = wc_get_product($product_id); $existing_download_ids = array_keys((array) $product->get_files()); $downloadable_ids = array_keys((array) $downloadable_files); $new_download_ids = array_filter(array_diff($downloadable_ids, $existing_download_ids)); if (!empty($new_download_ids)) { $existing_permissions = $wpdb->get_col($wpdb->prepare("SELECT order_id from {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE product_id = %d GROUP BY order_id", $product_id)); $subscriptions = wcs_get_subscriptions_for_product($product_id); foreach ($subscriptions as $subscription_id) { // only grant permissions to subscriptions which have no permissions for this product if (!in_array($subscription_id, $existing_permissions)) { $subscription = wcs_get_subscription($subscription_id); foreach ($new_download_ids as $download_id) { if ($subscription && apply_filters('woocommerce_process_product_file_download_paths_grant_access_to_new_file', true, $download_id, $product_id, $subscription)) { wc_downloadable_file_permission($download_id, $product_id, $subscription); } } } } } }