In this use case, we’ll look at a scenario where an office wants multiple users to be able to add items to a single cart. Then an office manager can access that cart, make edits and checkout from that cart.
We’ll assume we’ve already set up the following functions in our custom plugin:
(stuff we’ll glaze over to get to the Woo stuff)
/**
* Determines if user is an "office user" role
* @param int $user_id if null, uses get_current_user_id();
* @return boolean
*/
function cwpdev_user_is_office_user($user_id=null)
/**
* Get's the user_id of an office_user's office_manage for their group
* @param [type] $user_id [description]
* @return [type] [description]
*/
function cwpdev_get_office_manager_id($user_id)
The shared office cart will be a “persistent” cart. There are two user_meta_fields we’ll need to control to ensure this is loaded into the Office User’s cart:
We’ll use the WordPress core filters to control behavior on these meta fields.
apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
apply_filters( "delete_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $delete_all );
First, let’s ensure that office users always load the persistent cart on each WP run.
function cwpdev_office_users_load_cart($null, $object_id, $meta_key, $single){
if( cwpdev_user_is_office_user($object_id) && $meta_key === '_woocommerce_load_saved_cart_after_login'){
return true;
}
return $null;
}
add_filter('get_user_metadata', 'cwpdev_office_users_load_cart', 15, 4);
Next, We’ll ensure the cart that office users load is always the one that belongs to their office manager.
function cwpdev_office_user_shared_cart($null, $object_id, $meta_key, $single){
if ( cwpdev_is_office_user($object_id) && $meta_key === '_woocommerce_persistent_cart_'.get_current_blog_id() ){
$user_manager_id=cwpdev_get_office_manager_id(get_current_user_id());
return get_user_meta($user_manager_id, '_woocommerce_persistent_cart_'.get_current_blog_id(), true);
}
return $null;
}
add_filter('get_user_metadata', 'cwpdev_office_user_shared_cart', 15, 4);
In order to control which cart items a user can remove, we’ll need to designate an owner for each cart item when they add that item. We’ll use the ‘woocommerce_add_cart_item’ to accomplish this.
function cwpdev_mark_cart_item_owner($cart_item_array, $cart_item_key){
$cart_item_array['owner']=get_current_user_id();
return $cart_item_array;
}
add_filter('woocommerce_add_cart_item', 'cwpdev_mark_cart_item_owner', 15, 2);
Next we’ll need to ensure that, when the cart is updated, it actually updates the office manager’s cart.
function cwpdev_update_office_user_shared_cart($null, $object_id, $meta_key, $meta_value, $prev_value){
if ( cwpdev_is_office_user($object_id) && $meta_key === '_woocommerce_persistent_cart_'.get_current_blog_id() ){
$user_manager_id=cwpdev_get_office_manager_id(get_current_user_id());
return update_user_meta($user_manager_id, '_woocommerce_persistent_cart_');
}
return $null;
}
add_filter('update_user_metadata', 'cwpdev_update_office_user_shared_cart', 15, 5);
In order to control which cart items a user can remove, we’ll need to designate an owner for each cart item. We’ll use the ‘woocommerce_add_cart_item’ to accomplish this.
function cwpdev_mark_cart_item_owner($cart_item_array, $cart_item_key){
$cart_item_array['owner']=get_current_user_id();
return $cart_item_array;
}
add_filter('woocommerce_add_cart_item', 'cwpdev_mark_cart_item_owner', 15, 2);
Programmatically, its fairly easy to prevent an office user from removing an item that isn’t theirs from the cart:
function cwpdev_block_office_user_remove($cart_item_key, $cart){
if(! cwpdev_user_is_office_user() ){
return;
}
$cart_item_owner=$cart->get_cart_item($cart_item_key)['owner'] ?? -1;
if((int) $cart_item_owner !== get_current_user_id() ){
throw new Exception(__("You cannot remove or change another user's items from the cart") );
}
}
add_action('woocommerce_remove_cart_item', 'cwpdev_block_office_user_remove', 15, 2);
However, that’s not a great user experience…If a user sees a remove from cart link–it should work!
To have a user experience that makes sense, we’ll remove the remove cart links, where they do not apply:
function cwpdev_remove_remove_link_from_cart($link, $cart_item_key){
if(! cwpdev_user_is_office_user() ){
return $link;
}
$cart_item_owner=WC()->cart->get_cart_item($cart_item_key)["owner"] ?? -1;
if((int) $cart_item_owner !== get_current_user_id() ){
return '';
}
return $link;
}
add_filter('woocommerce_cart_item_remove_link', 'cwpdev_remove_remove_link_from_cart', 15, 2);
We’ve made this easy for ourselves, by adding the cwpdev_is_office_user() guard statements at the top of each of our hooks, office managers can expect normal cart behavior
Super easy:
function cwpdev_no_office_user_coupons($bool){
if( cwpdev_is_office_user()){
return false;
}
return $bool;
}
add_filter('woocommerce_coupons_enabled', 'cwpdev_no_office_user_coupons');
This is one that a little simpler to do by targetting templates and the payment gateways.
In your proceed-to-checkout-button template:
<?php if ( ! cwpdev_is_office_user() ): ?>
}
<a href="<?php echo esc_url( wc_get_checkout_url() ); ?>" class="checkout-button button alt wc-forward">
<?php esc_html_e( 'Proceed to checkout', 'woocommerce' ); ?>
</a>
<?php endif; ?>
function cwpdev_no_paygateway_for_office_user($gateways){
if( cwpdev_user_is_office_user() ){
return [];
}
return $gateways;
}
add_filter('woocommerce_available_payment_gateways', 'cwpdev_no_paygateway_for_office_user');
And block office users from payment gateways:
So we’ve managed to do a fairly comprehensive customization by staying within the boundaries of standard WooCommerce and WordPress filters.
So, when encountering a project that requires careful customization of the way WooCommerce progresses from users selections to building an order, review the flow charts and information in the previous topics. You will likely find an abundance of hooks and options available at your disposal 🙂
That’s all for this lesson, feel free to come back and search the materialRemember, CTRL+Shift+F can be used to do a word search in any of the topics! any time!