Reputation:
a week ago I've started to build a WooCommerce store which should have the option to share orders between two customers. Here is a little diagram I've made for you so you can understand how it should be (Please take a look at it):
So here is what I did step for step
User B clicks a button -> (Save second user id to the order):
$related_order = $_POST['related_order'];
$current_user = wp_get_current_user();
$userID = $current_user->ID;
update_post_meta($related_order, 'second_user_id', $userID);
User B clicks another button -> (Remove second user id from the order)
$related_order = $_POST['related_order'];
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
delete_post_meta($related_order , 'second_user_id');
These two steps (show and hide the order for user B) are working fine - I've tested it. The field gets set and unset.
Now it's getting worse:
I've searched a lot and asked some people to find the function in WooCommerce which gets all orders for a customer. After I found it I've tried to change it so that the second_user_id
field gets checked to. I simply thought that I can show the order from customer A to B this way:
function woocommerce_account_orders( $current_page ) {
$current_page = empty( $current_page ) ? 1 : absint( $current_page );
$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
'customer' => get_current_user_id(),
'second_user_id' => get_current_user_id(),
'page' => $current_page,
'paginate' => true,
) ) );
wc_get_template(
'myaccount/orders.php',
array(
'current_page' => absint( $current_page ),
'customer_orders' => $customer_orders,
'has_orders' => 0 < $customer_orders->total,
)
);
}
The method is located in: https://docs.woocommerce.com/wc-apidocs/source-function-woocommerce_account_orders.html#2465-2486
As you can see I've tried to add the second_user_id
to the query which returns the orders for a customer. This is my custom field saved in each order:
[5] => WC_Meta_Data Object (
[current_data:protected] => Array (
[id] => 3477
[key] => second_user_id
[value] => 2
)
After that did not worked I've got help from a friendly guy which told me, that this can't work the way I did it. There are permission which must be given to the user B to view the order from A and a lot of other stuff... So is there someone who can help me with this part? What is wrong with my implementation and how can I change the functionality the way I need it?
Upvotes: 0
Views: 896
Reputation: 3562
if we take look at the responsbile function which WooCommerce use to query the customer you will WooCommerceselect all orders which related to the user based on the user id.
Functions source code:
function woocommerce_account_orders( $current_page ) {
$current_page = empty( $current_page ) ? 1 : absint( $current_page );
$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
'customer' => get_current_user_id(),
'page' => $current_page,
'paginate' => true,
) ) );
wc_get_template(
'myaccount/orders.php',
array(
'current_page' => absint( $current_page ),
'customer_orders' => $customer_orders,
'has_orders' => 0 < $customer_orders->total,
)
);
}
}
If you want to alter this query and add specific order id's which is not belong to this user beside the default orders we need to do some sort of hack to this query and the possible option i can think of now is by using post__in
instead of getting the orders by customer id.
we are going to use the woocommerce_my_account_my_orders_query
filter to alter the query.
i will assume the additional orders for that user is stored in wp_usermeta
table
The Solution will be:
add_filter( 'woocommerce_my_account_my_orders_query', 'modify_my_order_query' , 20, 1 );
function modify_my_order_query( $q ) {
global $wpdb;
$current_user_id = get_current_user_id();
//Check if the user have addtional orders
$secondary_post_ids = get_user_meta( $current_user_id, 'additional_orders', false );
if ( ! empty( $secondary_post_ids ) ) {
// Get All Orders ID for the main customers
$prepare_query = $wpdb->prepare(
" SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key LIKE %s and meta_value LIKE %d ",
'_customer_user',
$current_user_id
);
$results = $wpdb->get_results( $prepare_query, ARRAY_A );
$main_post_ids = wp_list_pluck( $results, 'post_id' );
// Merge All Orders IDs
$all_posts_ids = ( isset( $secondary_post_ids[0] ) ) ? array_merge( $main_post_ids, $secondary_post_ids[0] ) : $main_post_ids;
//Modify the my Order Query to include all orders ID including the additional ones
unset( $q['customer'] );
$q['post__in'] = $all_posts_ids;
}
return $q;
}
you will see in the above solution first we check if the current user have additional order if yes then we select all his default orders id and merge the array with his additional order is and then we modified the query so we can get all those orders.
Now the only things left is to allow the user to see his additional orders and to do so we need to use user_has_cap
hook.
add_filter( 'user_has_cap', 'give_permissions' , 10, 3 );
function give_permissions( $allcaps, $cap, $args ) {
if ( isset( $cap[0] ) && $cap[0] == 'view_order' ) {
$get_additional_ids = get_user_meta( get_current_user_id(), 'additional_orders', false );
if ( isset( $get_additional_ids[0] ) && in_array( $args[2], $get_additional_ids[0] ) ) {
$allcaps[ $cap[0] ] = true;
}
}
return ( $allcaps );
}
i believe this solution will achieve your target goal.
Upvotes: 1