Having failed at adding a suffix based on User Role because it wont display the Woo price display shortcode, I'm now approach the problem from the other direction - I have added the suffix to Woos tax tab, and now instead want to remove the suffix (from all user roles except one).
I found this code on github to remove the suffix from products:
add_filter( 'woocommerce_get_price_suffix', 'custom_woocommerce_get_price_suffix', 10, 2 );
function custom_woocommerce_get_price_suffix( $price_display_suffix, $product ) {
if ( ! $product->is_taxable() ) {
return '';
}
return $price_display_suffix;
}
and I have modified it to hide the suffix from certain user types
add_filter( 'woocommerce_get_price_suffix', 'custom_woocommerce_get_price_suffix', 10, 2 );
function custom_woocommerce_get_price_suffix( $price_display_suffix, $product ) {
// check current user role
$user = wp_get_current_user();
$roles = ( array ) $user->roles;
if ( in_array( 'administrator', $roles ) ) {
$price = $your_suffix;
} elseif ( in_array( 'default_wholesaler', $roles ) ) {
$price = '$your_suffix';
return '';
}
return $price_display_suffix;
}
This worked, however I had to switch the users (I want Admin and Wholesalers to see the suffix) and put in Customers, etc.
The problem is that guest customers still see the suffix.
Could someone suggest a way of hiding the suffix from anyone except the logged in 'default-wholesaler' user and 'Administrator'?
Thanks!
You could use the following for this.
This works for the administrator role! you can add the other role yourself as an 'exercise'
function custom_woocommerce_get_price_suffix( $html, $product, $price, $qty ) {
// check current user role
$user = wp_get_current_user();
$roles = ( array ) $user->roles;
// if NOT in array user roles
if ( !in_array( 'administrator', $roles ) ) {
$html = '';
}
return $html;
}
add_filter( 'woocommerce_get_price_suffix', 'custom_woocommerce_get_price_suffix', 10, 4 );
Related
Woocommerce Settings:
Guest checkout disabled.
Create account during checkout enabled (user and passowrd auto generated)
If user is REGISTERED. But NOT logged in.
Checkout errors with
"An account is already registered with your email address. Please log in."
How do I override this to
COMPLETE order, and tie order to existing account.
Give a prompt to user to login next time for a faster checkout
Can't find any snippet or module that can do it
none yet. Happy to reward.
There is no hook for this. You may need to modify process_customer function in WC core (plugins/woocommerce/includes/class-wc-checkout.php) Line#935 - Keep in mind, it's not encouraged to edit core ( when updated, your changes will loose)
protected function process_customer( $data ) {
$customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );
if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
$username = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
$password = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
if(email_exists($data['billing_email'])){
$creds = array();
$creds['user_login'] = $user_login;
$creds['user_password'] = $user_password;
$creds['remember'] = true;
$user = wp_signon($creds, false);
$customer_id = $user->ID;
wp_set_current_user($customer_id, $user_login);
wp_set_auth_cookie($customer_id, true, false);
do_action('wp_login', $user_login);
}else{
$customer_id = wc_create_new_customer( $data['billing_email'], $username, $password );
}
if ( is_wp_error( $customer_id ) ) {
throw new Exception( $customer_id->get_error_message() );
}
wp_set_current_user( $customer_id );
wc_set_customer_auth_cookie( $customer_id );
// As we are now logged in, checkout will need to refresh to show logged in data.
WC()->session->set( 'reload_checkout', true );
// Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering.
WC()->cart->calculate_totals();
}
// On multisite, ensure user exists on current site, if not add them before allowing login.
if ( $customer_id && is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() ) {
add_user_to_blog( get_current_blog_id(), $customer_id, 'customer' );
}
// Add customer info from other fields.
if ( $customer_id && apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) {
$customer = new WC_Customer( $customer_id );
if ( ! empty( $data['billing_first_name'] ) ) {
$customer->set_first_name( $data['billing_first_name'] );
}
if ( ! empty( $data['billing_last_name'] ) ) {
$customer->set_last_name( $data['billing_last_name'] );
}
// If the display name is an email, update to the user's full name.
if ( is_email( $customer->get_display_name() ) ) {
$customer->set_display_name( $data['billing_first_name'] . ' ' . $data['billing_last_name'] );
}
foreach ( $data as $key => $value ) {
// Use setters where available.
if ( is_callable( array( $customer, "set_{$key}" ) ) ) {
$customer->{"set_{$key}"}( $value );
// Store custom fields prefixed with wither shipping_ or billing_.
} elseif ( 0 === stripos( $key, 'billing_' ) || 0 === stripos( $key, 'shipping_' ) ) {
$customer->update_meta_data( $key, $value );
}
}
/**
* Action hook to adjust customer before save.
*
* #since 3.0.0
*/
do_action( 'woocommerce_checkout_update_customer', $customer, $data );
$customer->save();
}
do_action( 'woocommerce_checkout_update_user_meta', $customer_id, $data );
}
If you have enabled allow customers to login on checkout, the option login from checkout page will be coming.
I want to hide Downloads from Woocommerce menu when user type is Artist.
Add this code to your theme's 'functions.php'.
function custom_my_account_menu_items( $items ) {
if( is_user_logged_in() ) {
$user = wp_get_current_user();
$role = ( array ) $user->roles;
if($role[0]=="artist") // change role name if different
unset($items['downloads']);
}
return $items;
}
add_filter( 'woocommerce_account_menu_items', 'custom_my_account_menu_items' );
I need a "get products A, B and C for $xxx" special offer, products A, B and C must be available on their own, and the bundle is a special offer accessible through a coupon code.
On a marketing page hosting outside my site, I would like a button leading to my site that carries a query string like ?add-to-cart=244,249,200 so that once on my site, all bundle products are already added to the cart (instead of adding them one by one which sounds unacceptably tedious).
If not possible, then at least I'd like a landing page on my site with a single button adding all bundle products to cart at once.
I couldn't find working solutions googling around (here's one example). Any suggestion?
After some research I found that DsgnWrks wrote a hook that does exactly this. For your convenience, and in case the blog goes offline, I bluntly copied his code to this answer:
function woocommerce_maybe_add_multiple_products_to_cart( $url = false ) {
// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
return;
}
// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
$count = count( $product_ids );
$number = 0;
foreach ( $product_ids as $id_and_quantity ) {
// Check for quantities defined in curie notation (<product_id>:<product_quantity>)
// https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/#comment-12236
$id_and_quantity = explode( ':', $id_and_quantity );
$product_id = $id_and_quantity[0];
$_REQUEST['quantity'] = ! empty( $id_and_quantity[1] ) ? absint( $id_and_quantity[1] ) : 1;
if ( ++$number === $count ) {
// Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
$_REQUEST['add-to-cart'] = $product_id;
return WC_Form_Handler::add_to_cart_action( $url );
}
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
$was_added_to_cart = false;
$adding_to_cart = wc_get_product( $product_id );
if ( ! $adding_to_cart ) {
continue;
}
$add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->get_type(), $adding_to_cart );
// Variable product handling
if ( 'variable' === $add_to_cart_handler ) {
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id );
// Grouped Products
} elseif ( 'grouped' === $add_to_cart_handler ) {
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id );
// Custom Handler
} elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ){
do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url );
// Simple Products
} else {
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id );
}
}
}
// Fire before the WC_Form_Handler::add_to_cart_action callback.
add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 );
/**
* Invoke class private method
*
* #since 0.1.0
*
* #param string $class_name
* #param string $methodName
*
* #return mixed
*/
function woo_hack_invoke_private_method( $class_name, $methodName ) {
if ( version_compare( phpversion(), '5.3', '<' ) ) {
throw new Exception( 'PHP version does not support ReflectionClass::setAccessible()', __LINE__ );
}
$args = func_get_args();
unset( $args[0], $args[1] );
$reflection = new ReflectionClass( $class_name );
$method = $reflection->getMethod( $methodName );
$method->setAccessible( true );
$args = array_merge( array( $class_name ), $args );
return call_user_func_array( array( $method, 'invoke' ), $args );
}
It works just like you'd expect, by providing a comma separated list of products. It even works with quantities using ?add-to-cart=63833:2,221916:4
I was, and am still looking for a 'pure' solution that allows to add multiple products to the cart without having to install a plugin or add custom actions. But for many, the above might be an appropriate solution
I am using this code which is partially working for changing the profile url everywhere in buddypress and wordpress from “http:/mywebsite/user/username” to “http:/mywebsite/user/userid”
function _bp_core_get_user_domain($domain, $user_id, $user_nicename = false, $user_login = false) {
if ( empty( $user_id ) ){
return;
}
if( isset($user_nicename) ){
$user_nicename = bp_core_get_username($user_id);
}
$after_domain = bp_get_members_root_slug() . '/' . $user_id;
$domain = trailingslashit( bp_get_root_domain() . '/' . $after_domain );
$domain = apply_filters( 'bp_core_get_user_domain_pre_cache', $domain, $user_id, $user_nicename, $user_login );
if ( !empty( $domain ) ) {
wp_cache_set( 'bp_user_domain_' . $user_id, $domain, 'bp' );
}
return $domain;
}
add_filter('bp_core_get_user_domain', '_bp_core_get_user_domain', 10, 4);
function _bp_core_get_userid($userid, $username){
if(is_numeric($username)){
$aux = get_userdata( $username );
if( get_userdata( $username ) )
$userid = $username;
}
return $userid;
}
add_filter('bp_core_get_userid', '_bp_core_get_userid', 10, 2);
function _bp_get_activity_parent_content($content){
global $bp;
$user = get_user_by('slug', $bp->displayed_user->fullname); // 'slug' - user_nicename
return preg_replace('/href=\"(.*?)\"/is', 'href="'.bp_core_get_user_domain($user->ID, $bp->displayed_user->fullname).'"', $content);
}
add_filter( 'bp_get_activity_parent_content','_bp_get_activity_parent_content', 10, 1 );
add_filter('bp_core_get_userid_from_nicename', '_bp_core_get_userid', 10, 2);
It is working perfectly for me at the moment BUT not on this little place (see picture):
http://i.imgur.com/4dX0RUB.png
– url change of the author of an activity starting-message is not working in both groups activities and personnal activities
url change of the author of an activity REPLY is working
I don’t know if I am explaining very well what issue I have got but I hope you will understand.
Thank you for your answers
PS : thanks to aSeptik from StackExchange for the code
It's impossible to do that on a fly gracefully. BuddyPress Activity component is developed in such a way, that those text with the user link in activity stream (for site-wide, personal and groups) is stored directly in the database as an action. Just take a look at wp_bp_activity.action field in your DB.
So you should filter and preg_replace it as well. I guess you know that you are penalting yourself with rendering speed loss.
Is there a way to display an extra text next to the Username if the person has the administrator role?
I just want to display the extra text for this role only, what hook could I use for that?
Yes, you can use the filter the_author, like so:
add_filter( 'the_author', 'author_admin_so_14367149' );
function author_admin_so_14367149( $display_name )
{
// Block the filter in the dashboard (admin area)
if( is_admin() )
return $display_name;
global $authordata;
// User has administrator role, add string to display name
if( in_array( 'administrator', $authordata->roles ) )
$display_name = $display_name . ' (admin)';
return $display_name;
}
For the comments section, there's another filter and the checks are different:
add_filter( 'get_comment_author', 'comment_author_admin_so_14367149' );
function comment_author_admin_so_14367149( $author )
{
// Block the filter in the dashboard (admin area)
if( is_admin() )
return $author;
$user = get_user_by( 'login', $author );
// User has administrator role, add string to display name
if( in_array( 'administrator', $user->roles ) )
$author = $author . ' (admin)';
return $author;
}