this is my first question here, I can not find a solution for this:
We are running am e-learning platform along with the e-commerce system for selling the courses, which can be purchased by two ways, the full price or a monthly subscription, all of this mounted with WordPress (Sensei + WooCommerce - Subscriptions addon installed - )
WoordPress Ver.: 4.5.2
WooCommerce Ver.: 2.5.5
Subscription Ver.: 2.1.2
In order to let the user enter the course we need to check if that user have an active/completed subscription or a completed order.
First problem, subscriptions does not have a completed status, instead the system mark them as cancelled, I understand that a complete subscription is one in which all payments have been completed, so this function is totally useless:
wcs_user_has_subscription( $user_id, $product_id, 'cancelled' )
Because a cancelled subscription may have missing payments.
So I created this function:
foreach ( wcs_get_users_subscriptions( $user_id ) as $subscription ) {
$sub_wc = new WC_Subscription( $subscription->id );
// Only for testing, we only need the first product.
$product = reset( $sub_wc->get_items() );
$done_payments = $sub_wc->get_completed_payment_count();
$total_payments = WC_Subscriptions_Product::get_length( $item['product_id'] );
if( ( $total_payments == $done_payments ) || $sub_wc->post_status == 'wc-active' ) {
$result = true;
}
}
And if that functions returns false (I have summarized, omitting the return
) we need to check for completed orders, but not related with a subscription because each subscription can have more than one order (parent, renewal, etc), so this function is useless:
wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id )
And you might ask, why?
That functions works fine if you are not working with subscriptions, remember that a cancelled subscription can have 2 completed orders, and this function will return true
because it does not matter if the order is related to a subscription.
So for this case I created this function:
$user_completed_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user->ID,
'post_type' => 'shop_order',
'post_status' => 'wc-completed'
) );
foreach ( $completed_orders as $completed_order ) {
$order_wc = new WC_Order( $completed_order->ID );
// We only want orders not related with any subscriptions
if( !wcs_order_contains_subscription( $order_wc ) ) {
// Check if the user purchased the product
// Only for testing, we only need the first product.
$product = reset( $order_wc->get_items() );
if( $product['product_id'] == $product_id ) {
$result = true;
}
}
}
All this causes the load to increase, and we go from about 6-7 seconds of load to 14, I know it is not much, but it pisses me off that there are no defined functions for this.
Do you think there is a better approach for this particular case?
Improve the code above?
Maybe I'm missing an official function/method?
Thanks community, sorry for the long post and for any spelling mistakes that may have. Have a good day.