replacing "view cart" button with "proceed to checkout" button upon adding a product to cart - notifications

After product page reloads upon adding the product to cart, a notification appears on top saying "product was added to cart" followed by a "view cart" button.
However after product gets added to cart I want to direct customers to checkout page (where I'll add cart page functionality), not cart page. How can I replace the notification's link to cart with a link to checkout page?
wc_add_to_cart_message() function (in includes/wc-cart-functions.php) seems to generate this particular notification, should I override this function? If so, how?

try this...
function rei_wc_add_to_cart_message( $message, $product_id ) {
$titles = array();
if ( is_array( $product_id ) ) {
foreach ( $product_id as $id ) {
$titles[] = get_the_title( $id );
}
} else {
$titles[] = get_the_title( $product_id );
}
$titles = array_filter( $titles );
$added_text = sprintf( _n( '%s has been added to your cart.', '%s have been added to your cart.', sizeof( $titles ), 'woocommerce' ), wc_format_list_of_items( $titles ) );
// Output success messages
if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
$return_to = apply_filters( 'woocommerce_continue_shopping_redirect', wp_get_referer() ? wp_get_referer() : home_url() );
$message = sprintf( '%s %s', esc_url( $return_to ), esc_html__( 'Continue Shopping', 'woocommerce' ), esc_html( $added_text ) );
} else {
$message = sprintf( '%s %s', esc_url( wc_get_page_permalink( 'checkout' ) ), esc_html__( 'Proceed to Checkout', 'woocommerce' ), esc_html( $added_text ) );
}
return $message;
}
add_filter('wc_add_to_cart_message','rei_wc_add_to_cart_message',10,2);

Related

Get product total sales based on order status in WooCommerce

I use product meta total_sales to display the total sales of a product, on the single product page in WooCommerce:
add_action( 'woocommerce_single_product_summary', 'wc_product_sold_count', 11 );
function wc_product_sold_count() {
global $product;
$units_sold = get_post_meta( $product->get_id(), 'total_sales', true );
echo '<p>' . sprintf( __( 'Units Sold: %s', 'woocommerce' ), $units_sold ) . '</p>';
}
But when some orders are canceled, the total sales are not automatically decreased. So, how can I get the total sales based on order status in WooCommerce?
To obtain the total sales, based on order statuses, you will have to use a custom function:
function get_product_total_sales_by_order_status( $product_id, $order_statuses ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare("
SELECT SUM( opl.product_qty )
FROM {$wpdb->prefix}wc_order_product_lookup as opl
INNER JOIN {$wpdb->prefix}posts as p
ON opl.order_id = p.ID
AND p.post_status IN ( 'wc-" . implode( "', 'wc-", $order_statuses ) . "' )
AND opl.product_id = %d
", $product_id ) );
}
Which can then be used as:
// Set the product ID
$p_id = 30;
// Set the orders statuses (without wc-)
$statuses = array( 'on-hold', 'processing', 'completed' );
// Call function, display result
echo get_product_total_sales_by_order_status( $p_id, $statuses );
Or in your specific case:
function action_woocommerce_single_product_summary() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Set the orders statuses (without wc-)
$statuses = array( 'completed' );
// Call function
$total_sales = get_product_total_sales_by_order_status( $product->get_id(), $statuses );
// Display result
if ( $total_sales >= 1 ) {
echo sprintf( __( 'Total sales: %d', 'woocommerce' ), $total_sales );
} else {
echo __( 'N/A', 'woocommerce' );
}
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 11 );

Display In stock available variations in WooCommerce single product

I have variable products with many variations where only a few items are actually In Stock while the majority of other variations are ''available on backorder''
I would like to be able to display a quick list of ONLY the items that are IN STOCK in the short product description of each product page so the customer doesn't have to try all variations one-by-one to finally find out which ones are in stock.
add_filter( 'woocommerce_short_description', 'display_in_stock_variations_to_short_description' );
function display_in_stock_variations_to_short_description( $excerpt ){
global $product;
if ( ! is_product() || empty($product) || ! is_a( $product, 'WC_Product' ) )
return $excerpt;
if( $product->is_type('variable') ) {
// Loop through visible children
foreach( $product->get_children() as $variation_id ) {
$variation = wc_get_product( $variation_id );
// Hide out of stock variations if 'Hide out of stock items from the catalog' is checked.
if ( ! $variation || ! $variation->exists() || ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) {
continue;
}
// Filter 'woocommerce_hide_invisible_variations' to optionally hide invisible variations (disabled variations and variations with empty price).
if ( apply_filters( 'woocommerce_hide_invisible_variations', true, $product->get_id(), $variation ) && ! $variation->variation_is_visible() ) {
continue;
}
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
$term_names = []; // Initializing
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_slug ) {
// Set the term name in an array
$term_names[] = ucfirst( str_replace( ['-', '_'],[' ', ' '], $term_slug ) );
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('in stock', 'woocommerce')
);
}
}
}
return $excerpt;
}
// Avoid additional content from product short description to be displayed in variation description
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_desscription', 10, 3);
function filter_wc_available_variation_desscription( $data, $product, $variation ) {
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
if( $max_qty > 0 )
$data['variation_description'] = get_post_meta( $variation->get_id(), '_variation_description', true );
return $data;
}
This code displays an inventory, but my website language is Persian and the names of the variables are defined in Persian, and this line does not display the variable name code correctly.
How can I fix his language?
And I want to translate the word instock into موجود
And the next point is that I want a button to be displayed on the page first with the title Show product inventory and when the method clicks, the customer will open a pop-up and display the inventory.
Here is the soultion with Persian language:
change
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_slug ) {
// Set the term name in an array
$term_names[] = ucfirst( str_replace( ['-', '_'],[' ', ' '], $term_slug ) );
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('in stock', 'woocommerce')
);
}
to
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_name ) {
// Set the term name in an array
$taxonomy = str_replace('attribute_', '', $attribute);
$attribute_name = wc_attribute_label($taxonomy);
$term_name = get_term_by( 'slug', $term_name, $taxonomy)->name;
$term_names[] = $term_name;
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('موجود')
);
}

Gravityform - update ACF Repeater subfield mixed with dynamic pre-populate fields

I have an ACF repeater field that create Courses with a certain amount of place available. This repeater is on each single custom-post-type courses.
In the other hand, I have a Gravityform that have a radio field who is auto-populated with those ACF repeater:
add_filter( 'gform_pre_render_3', 'populate_posts' );
add_filter( 'gform_pre_validation_3', 'populate_posts' );
add_filter( 'gform_pre_submission_filter_3', 'populate_posts' );
add_filter( 'gform_admin_pre_render_3', 'populate_posts' );
function populate_posts( $form ) {
foreach ( $form['fields'] as &$field ) {
// Vient check tous les fields du formulaire
if ( $field->type != 'radio' || strpos( $field->cssClass, 'populate-posts' ) === false ) {
// Choisit seulement les fields de type [radio] qui ont la class [populate-posts]
continue;
}
$date_type = get_field( 'date_type' );
$range_dates = get_field( 'date_range_repeater' );
$sinlge_dates = get_field( 'sinlge_dates_repeater' );
$choices = array();
if( $date_type === 'date_type_range' ){
foreach ( $range_dates as $range_date ) {
$dateformatstring = "j F Y";
$dateclean_start = strtotime( $range_date['date_starting'] );
$final_date_start = date_i18n($dateformatstring, $dateclean_start);
$dateclean_end = strtotime( $range_date['date_ending'] );
$final_date_end = date_i18n($dateformatstring, $dateclean_end);
$choices[] = array(
'text' => 'Du '.$final_date_start.' au '.$final_date_end.'<br />'.$range_date['availability'].' places disponibles',
'value' => 'Du '.$final_date_start.' au '.$final_date_end
);
}
}elseif( $date_type === 'date_type_single' ){
foreach ( $sinlge_dates as $sinlge_date ) {
$dateformatstring = "j F Y";
$dateclean_start = strtotime( $sinlge_date['date_starting'] );
$final_date_start = date_i18n($dateformatstring, $dateclean_start);
$dateclean_end = strtotime( $sinlge_date['date_ending'] );
$final_date_end = date_i18n($dateformatstring, $dateclean_end);
$choices[] = array(
'text' => 'Du '.$final_date_start.' au '.$final_date_end.'<br />'.$sinlge_date['availability'].' places disponibles',
'value' => 'Du '.$final_date_start.' au '.$final_date_end
);
}
}else{}
// update 'Select a Post' to whatever you'd like the instructive option to be
$field->placeholder = 'Select a Post';
$field->choices = $choices;
}
return $form;
}
I want that after each submission the available place number decrease from 1. I have figured out how to manage this with this ACF function:
https://www.advancedcustomfields.com/resources/update_sub_field/
This is my code for this:
add_action( 'gform_after_submission', 'set_post_content', 10, 2 );
function set_post_content( $entry, $form ) {
//$radio_value = rgar( $entry, '11' );
$repeater = 'date_range_repeater';
$acf_repeater = get_field('date_range_repeater' ); // get all the rows
$row = 0;
$specific_row = $acf_repeater[$row];
$sub_field = 'availability';
$current_availability = $specific_row['availability'];
$availability_new = --$current_availability;
update_sub_field( array($repeater, ++$row, $sub_field), $availability_new );
//echo $radio_value;
}
The thing is I have to select manually which row must be used to update de subfield. How can I manage to detect in which ACF repeater row is my submitted value ?
Thanks !
Maybe you can add some hidden fields in your GF and populate them in your function populate_posts( $form ){}like that you should have accessible directly in your after_submit function.

Disable WooCommerce email notification for specific product

I can refer to this function to disable email notification:
https://docs.woocommerce.com/document/unhookremove-woocommerce-emails/
But I would like to disable it only for a specific product or, if it can be more simple, for a specific product category.
Thanks for your help
Thanks to #vidish-purohit for the help!
Here is my code to use if you need to disable admin email notification for a specific product:
function change_email_recipient_depending_of_product_id( $recipient, $order ) {
global $woocommerce;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( $product_id == xxx ) {
$recipient = '';
}
return $recipient;
}
}
add_filter( 'woocommerce_email_recipient_new_order', 'change_email_recipient_depending_of_product_id', 10, 2 );
And if you need to disable customer email notification for a specific product:
function change_email_recipient_depending_of_product_id( $recipient, $order ) {
global $woocommerce;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( $product_id == xxx ) {
$recipient = '';
}
return $recipient;
}
}
add_filter( 'woocommerce_email_recipient_customer_processing_order', 'change_email_recipient_depending_of_product_id', 10, 2 );
I think when you try to hook email notification from template, where you can find order, at that time emails are already sent.
You can try one thing - using recipient's hook you can remove recipient email and return empty string. Or if empty string triggers error, then you can give some dummy email.
Use this code for this:
// Change new order email recipient for registered customers
function wc_change_admin_new_order_email_recipient( $recipient, $order ) {
global $woocommerce;
// check if product in order
if ( true ) ) {
$recipient = "";
} else {
$recipient = "newbusiness#yourdomain.com";
}
return $recipient;
}
add_filter('woocommerce_email_recipient_new_order', 'wc_change_admin_new_order_email_recipient', 1, 2);
// Change new order email recipient for registered customers
function wc_change_admin_new_order_email_recipient( $recipient, $order ) {
$flagHasProduct = false;
// Get items in order
$items = $order->get_items();
// Loop for all items
foreach ( $items as $item ) {
$product_id = $item['product_id'];
// check if specific product is in order
if ( $product_id == 102 ) {
$flagHasProduct = true;
}
}
// if product is found then remove recipient
if ($flagHasProduct) {
$recipient = "";
} else {
$recipient = "newbusiness#yourdomain.com";
}
return $recipient;
}
add_filter('woocommerce_email_recipient_new_order', 'wc_change_admin_new_order_email_recipient', 1, 2);
The above code will disable the email option in the Woocommerce email setting option page.
/**
* Disable Admin email Notification for Specific Product
*/
function cstm_change_email_recipient_for_giftcard_product($recipient, $order)
{
// Bail on WC settings pages since the order object isn't yet set yet
// Not sure why this is even a thing, but shikata ga nai
$page = $_GET['page'] = isset($_GET['page']) ? $_GET['page'] : '';
if ('wc-settings' === $page) {
return $recipient;
}
// just in case
if (!$order instanceof WC_Order) {
return $recipient;
}
$items = $order->get_items();
foreach ($items as $item) {
$product_id = $item['product_id'];
if ($product_id == xxxx) {
$recipient = '';
}
return $recipient;
}
}
add_filter('woocommerce_email_recipient_new_order', 'cstm_change_email_recipient_for_giftcard_product', 10, 2);
this code works fine in latest version of Woocommerce.

Woocommerce how do I redirect to a Specific Page upon Login?

When a user logs in Woocommerce open the MyAccount Page
I need to go to detailing a range of Services we offer.
On that page I want to set a Tick Box if they agree to be called by our Sales staff.
If the users selects this - I would like to set a Session variable which I can use at Cart.
Here are some snippets that will guide you to do that
After login:-
// Custom redirect for users after logging in
add_filter('woocommerce_login_redirect', 'wcs_login_redirect');
function wcs_login_redirect( $redirect ) {
$redirect = 'http://google.com/';
return $redirect;
}
After login but just after register:-
// Custom redirect for users after logging in
add_filter('woocommerce_registration_redirect', 'wcs_register_redirect');
function wcs_register_redirect( $redirect ) {
$redirect = 'http://google.com/';
return $redirect;
}
Redirect the user based on their role :-
function wc_custom_user_redirect( $redirect, $user ) {
// Get the first of all the roles assigned to the user
$role = $user->roles[0];
$dashboard = admin_url();
$myaccount = get_permalink( wc_get_page_id( 'myaccount' ) );
if( $role == 'administrator' ) {
//Redirect administrators to the dashboard
$redirect = $dashboard;
} elseif ( $role == 'shop-manager' ) {
//Redirect shop managers to the dashboard
$redirect = $dashboard;
} elseif ( $role == 'editor' ) {
//Redirect editors to the dashboard
$redirect = $dashboard;
} elseif ( $role == 'author' ) {
//Redirect authors to the dashboard
$redirect = $dashboard;
} elseif ( $role == 'customer' || $role == 'subscriber' ) {
//Redirect customers and subscribers to the "My Account" page
$redirect = $myaccount;
} else {
//Redirect any other role to the previous visited page or, if not available, to the home
$redirect = wp_get_referer() ? wp_get_referer() : home_url();
}
return $redirect;
}
add_filter( 'woocommerce_login_redirect', 'wc_custom_user_redirect', 10, 2 );