Change account menu wording if user is "logged in" in WooCommerce - php

I'm using WooCommerce with a child theme of Storefront.
I have a secondary menu named "Desktop secondary top right EN" where there's a link to "my account".
My question is: how to change the "my account" item wording if the customer is logged in ?
I'd like to do this without having to create another menu in the back office and without installing a plugin of course.
I should be able to use something similar to:
function menu_add_admin_buttons( $items, $args ) {
if( 'secondary' == $args['theme_location'] ) {
$btn_format = '<li>%s</li>';
if ( is_user_logged_in() ) {
$btn = sprintf($btn_format, admin_url('profile.php'), __('Your Profile') );
} else {
$btn = sprintf($btn_format, wp_login_url(), __('Log In') );
}
return $items . $btn;
}
}
$menu_filter = 'wp_nav_menu_' . sanitize_title("Desktop secondary top right EN") . '_items';
add_filter($menu_filter, 'menu_add_admin_buttons', 20, 2);
but it has to be customized to my needs. How can I do this?

You can try another wordpress hook wp_nav_menu_items:
function menu_add_admin_buttons( $items, $args ) {
$btn = '';
if ( $args->theme_location === 'secondary' ) {
$btn_format = '<li>%s</li>';
if ( is_user_logged_in() ) {
$btn = sprintf($btn_format, admin_url( 'profile.php' ), __( 'Your Profile' ) );
} else {
$btn = sprintf($btn_format, wp_login_url(), __('Log In') );
}
}
return sprintf( '%s%s', $items, $btn );
}
add_filter( 'wp_nav_menu_items','menu_add_admin_buttons', 10, 2 );
Could you please to check the documentation.

I did this instead, and it seems to work fine.
I use the standard hook : wp_setup_nav_menu_item to filter the menu items.
I check if it's not the back office (admin mode) and if woocommerce is active.
Then, if the url is the url of the "my account" menu, I make the change according to the current language.
add_filter( 'wp_setup_nav_menu_item','my_account_setup' );
function my_account_setup( $item ) {
if ( ! is_admin() && class_exists( 'woocommerce' ) ) {
if ( $item->url == esc_url( wp_login_url() ) || strpos($item->url, '/my-account-2-2/') !== false ){
if ( is_user_logged_in() ) {
if(get_locale() == 'fr_FR') {
$item->title = 'MON COMPTE';
} else {
$item->title = 'MY ACCOUNT';
}
} else {
if(get_locale() == 'fr_FR') {
$item->title = 'LOGIN';
} else {
$item->title = 'LOGIN';
}
}
}
}
return $item;
}

Related

Validating custom checkout fields in admin edit order form

I'm trying to add validation to some checkout fields when editing an order from admin panel, but I haven't found the hook for that. I want to prevent saving post if validation fails and also show a notice. I've tried woocommerce_process_shop_order_meta hook but post is always saved and notices are not shown.
This is the code I used in my functions.php file:
$meta_box_errors[] = array();
add_action( 'woocommerce_process_shop_order_meta', 'save_order_custom_field_meta_data', 12, 2 );
public function save_order_custom_field_meta_data( $post_id, $post ){
$field_name = 'billing_nif';
$nif_value = '';
if( isset( $_POST[ '_' . $field_name ] ) && !empty($_POST[ '_' . $field_name ]) ) {
$nif_value = sanitize_text_field( $_POST[ '_' . $field_name ] );
if (!empty ($nif_value)) {
if (! validate_nif( $nif_value )) {
$meta_box_errors["invalid_nif"] = 'Invalid NIF';
}
} else {
$meta_box_errors["empty_nif"] = 'Empty NIF';
}
} else {
$meta_box_errors["empty_nif"] = 'Empty NIF';
}
if( ! empty( $this->meta_box_errors ) ) {
add_action( 'admin_notices', 'output_errors' );
}
}
public function validate_nif( $nif ){
$nif = strtoupper($nif);
if (strlen($nif) != 9) {
return false;
}
$nifExp = "^((\d{8})([A-Z]{1}))$^";
return preg_match($nifExp, $nif));
}
public function output_errors() {
echo '<div id="woocommerce_errors" class="error notice is-dismissible">';
foreach ( $meta_box_errors as $error ) {
echo '<p>' . wp_kses_post( $error ) . '</p>';
}
echo '</div>';
unset($meta_box_errors);
}

Display SKU in Woocommerce single product page with OceanWP theme

I want to display the SKU field of each product in its signle product page. The woocommerce plugin's settings does not have that option in wordpress.
I already followed the instructions here:
https://wordpress.stackexchange.com/questions/219410/how-to-show-product-sku-on-product-page/219427#219427
I tried adding to my functions.php file this code:
add_action( 'woocommerce_single_product_summary', 'dev_designs_show_sku', 5 );
function dev_designs_show_sku(){
global $product;
echo 'SKU: ' . $product->get_sku();
}
And also tried to add this code to the theme's single product content file:
if ( 'sku' === $element ) {
woocommerce_template_single_sku();
}
file name is owp-single-product.php:
<?php
/**
* Single product template.
*
* #package OceanWP WordPress theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
// Get price conditional display state.
$ocean_woo_single_cond = get_theme_mod( 'ocean_woo_single_conditional', false );
// Conditional vars.
$show_woo_single = '';
$show_woo_single = ( is_user_logged_in() && $ocean_woo_single_cond === true );
/**
* Display Single Product template
*
*/
// Get elements.
$elements = oceanwp_woo_summary_elements_positioning();
// Loop through elements.
foreach ( $elements as $element ) {
do_action( 'ocean_before_single_product_' . $element );
// Title.
if ( 'title' === $element ) {
woocommerce_template_single_title();
}
// Sku.
if ( 'sku' === $element ) {
woocommerce_template_single_sku();
}
// Rating.
if ( 'rating' === $element ) {
woocommerce_template_single_rating();
}
// Price.
if ( 'price' === $element ) {
if ( false === $ocean_woo_single_cond || $show_woo_single ) {
woocommerce_template_single_price();
}
}
// Excerpt.
if ( 'excerpt' === $element ) {
woocommerce_template_single_excerpt();
}
// Quantity & Add to cart button.
if ( 'quantity-button' === $element ) {
if ( false === $ocean_woo_single_cond || $show_woo_single ) {
woocommerce_template_single_add_to_cart();
} else {
// Get Add to Cart button message display state.
$ocean_woo_single_msg = get_theme_mod( 'ocean_woo_single_cond_msg', 'yes' );
if ( 'yes' === $ocean_woo_single_msg ) {
// Get Add to Cart button replacement message.
$ocean_woo_single_msg_txt = get_theme_mod( 'ocean_woo_single_cond_msg_text' );
$ocean_woo_single_msg_txt = $ocean_woo_single_msg_txt ? $ocean_woo_single_msg_txt : esc_html__( 'Log in to view price and purchase', 'oceanwp' );
$woo_single_myaccunt_link = get_theme_mod( 'ocean_single_add_myaccount_link', false );
echo '<div class="owp-woo-single-cond-notice">';
if ( false === $woo_single_myaccunt_link ) {
echo '<span>'. $ocean_woo_single_msg_txt .'</span>';
} else {
echo '' . $ocean_woo_single_msg_txt . '';
}
echo '</div>';
}
}
}
// Meta.
if ( 'meta' === $element ) {
woocommerce_template_single_meta();
}
do_action( 'ocean_after_single_product_' . $element );
}
Did not work! What do I do?
You can try this to show the sku after product title
add_action( 'ocean_after_single_product_title', 'show_product_sku', 5 );
function show_product_sku(){
global $product;
echo 'SKU: ' . $product->get_sku();
}

Hide a custom action button on click displaying a text in WooCommerce admin orders list

I am creating woocommerce plugin to send order details via WhatsApp. Here is my plugin code
add_filter( 'manage_edit-shop_order_columns', 'dvs_whatsapp_msg_list_column' );
function dvs_whatsapp_msg_list_column( $columns ) {
$columns['dvs_show_whatsapp'] = 'WhatsApp';
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'dvs_whatsapp_msg_list_column_content' );
function dvs_whatsapp_msg_list_column_content( $column ) {
global $post;
if ( 'dvs_show_whatsapp' === $column ) {
$order = wc_get_order( $post->ID );
$firstname = $order->get_billing_first_name();
$lastname = $order->get_billing_last_name();
$phone = $order->get_billing_phone();
$ordernum = $order->get_order_number();
$total = $order->get_total();
$payment = $order->get_payment_method_title();
$country = $order->get_billing_country();
$calling_code = WC()->countries->get_country_calling_code($country);
$whatsappnum = $calling_code.$phone;
$msg = 'Hello ' .$firstname. ' ' .$lastname. ', your order #' .$ordernum. ' has been received. The order amount is ' .$total. '. Your payment method is ' .$payment. '. Please contact us if you have any question regarding your order. Thank you.';
echo 'Send WhatsApp';
}
}
This is output
I want when shop manager or admin click the Send Whatsapp link then it will hide the link and show Message sent so shop manager or admin can know the details of this msg is already sent.
Please help.
Javascript is not the way to achieve this. You will use the following instead to hide the link and display "Message sent" once an external link has been clicked:
add_filter( 'manage_edit-shop_order_columns', 'dvs_whatsapp_msg_list_column' );
function dvs_whatsapp_msg_list_column( $columns ) {
$columns['whatsapp'] = __('WhatsApp', 'woocommerce');
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'dvs_whatsapp_msg_list_column_content' );
function dvs_whatsapp_msg_list_column_content( $column ) {
if ( 'whatsapp' === $column ) {
global $the_order;
if( ! $the_order->get_meta('_wapp_sent') ) {
echo '' . __("Send WhatsApp") . '';
}
else {
echo __("Message sent", "woocommerce");
}
}
}
add_action( 'admin_init', 'dvs_redirect_whatsapp_send' );
function dvs_redirect_whatsapp_send() {
global $pagenow;
# Check current admin page.
if ( $pagenow == 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] == 'shop_order'
&& isset($_GET['send']) && $_GET['send'] == 'dvs_whatsapp' && isset($_GET['order_id']) && $_GET['order_id'] > 0 ) {
$order = wc_get_order( $_GET['order_id'] );
$msg = sprintf( __("Hello %s %s, your order #%s has been received. The order amount is %s. Your payment method is %s. %s", "woocommerce"),
$order->get_billing_first_name(),
$order->get_billing_last_name(),
$order->get_order_number(),
$order->get_total(),
$order->get_payment_method_title(),
__("Please contact us if you have any question regarding your order. Thank you.", "woocommerce")
);
$whatsapp_num = WC()->countries->get_country_calling_code( $order->get_billing_country() ) . $order->get_billing_phone();
update_post_meta( $_GET['order_id'], '_wapp_sent', 'true' ); // Mark order as WhatsApp message sent
wp_redirect( 'https://wa.me/' . $whatsappnum . '?text=' . urlencode($msg) ); // Redirect to WhatsApp sending service
exit;
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I believe this should do the trick:
jQuery to insert on your page
jQuery('.dvs-whatsapp-btn').click(function(){
jQuery('<span class="link-clicked">Link clicked!</span>').insertAfter('.dvs-whatsapp-btn');
jQuery('.dvs-whatsapp-btn').hide();
});

WooCommerce - redirect to previous page after login

I've been searching for plugins and snippets which would handle it for hours, but no success. Every single answer doesn't work for me. I have "Log in" link in menu, leading to WooCommerce "My account" page, which shows login form. I want customers to return to page where "Log in" link was clicked after successful login.
wp_get_referer() doesn't return anything and $_SERVER["HTTP_REFERER"] returns my account page if put within function hooked to woocommerce_login_redirect (I used PHP debug console to check).
Here is my code:
// Redirect user after login.
add_filter( 'woocommerce_login_redirect', 'wc_custom_user_redirect', 10, 2 );
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();
if (in_array($role, array('administrator', 'shop_manager', 'editor', 'author', 'contributor'))) {
$redirect = $dashboard;
} elseif (in_array($role, array('customer', 'subscriber'))) {
$redirect = $_SERVER["HTTP_REFERER"];
} else {
$redirect = $_SERVER["HTTP_REFERER"];
}
return $redirect;
}
Here is where filter which I used appears in WooCommerce code:
/**
* Process the login form.
*/
public static function process_login() {
$nonce_value = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
$nonce_value = isset( $_POST['woocommerce-login-nonce'] ) ? $_POST['woocommerce-login-nonce'] : $nonce_value;
if ( ! empty( $_POST['login'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
try {
$creds = array(
'user_password' => $_POST['password'],
'remember' => isset( $_POST['rememberme'] ),
);
$username = trim( $_POST['username'] );
$validation_error = new WP_Error();
$validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $_POST['username'], $_POST['password'] );
if ( $validation_error->get_error_code() ) {
throw new Exception( '<strong>' . __( 'Error:', 'woocommerce' ) . '</strong> ' . $validation_error->get_error_message() );
}
if ( empty( $username ) ) {
throw new Exception( '<strong>' . __( 'Error:', 'woocommerce' ) . '</strong> ' . __( 'Username is required.', 'woocommerce' ) );
}
if ( is_email( $username ) && apply_filters( 'woocommerce_get_username_from_email', true ) ) {
$user = get_user_by( 'email', $username );
if ( isset( $user->user_login ) ) {
$creds['user_login'] = $user->user_login;
} else {
throw new Exception( '<strong>' . __( 'Error:', 'woocommerce' ) . '</strong> ' . __( 'A user could not be found with this email address.', 'woocommerce' ) );
}
} else {
$creds['user_login'] = $username;
}
// On multisite, ensure user exists on current site, if not add them before allowing login.
if ( is_multisite() ) {
$user_data = get_user_by( 'login', $username );
if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
}
}
// Perform the login
$user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), is_ssl() );
if ( is_wp_error( $user ) ) {
$message = $user->get_error_message();
$message = str_replace( '<strong>' . esc_html( $creds['user_login'] ) . '</strong>', '<strong>' . esc_html( $username ) . '</strong>', $message );
throw new Exception( $message );
} else {
if ( ! empty( $_POST['redirect'] ) ) {
$redirect = $_POST['redirect'];
} elseif ( wp_get_referer() ) {
$redirect = wp_get_referer();
} else {
$redirect = wc_get_page_permalink( 'myaccount' );
}
wp_redirect( apply_filters( 'woocommerce_login_redirect', $redirect, $user ) );
exit;
}
} catch ( Exception $e ) {
wc_add_notice( apply_filters( 'login_errors', $e->getMessage() ), 'error' );
do_action( 'woocommerce_login_failed' );
}
}
}
I tried the answer of #dineshkashera but it throws an error as starting a session is not a good practice and also wp_get_referer hook is not working and thus $_SERVER['HTTP_REFERER'].
So my only solution is creating a cookie that will save our previous link.
Here's my Code:
//First we need to set a cookie that will save the previous url
setcookie('nlcrc', $_SERVER['HTTP_REFERER'], time() + 86000, COOKIEPATH, COOKIE_DOMAIN, false);
//Then initiate Woocommerce redirect hook
//This is for the WC login redirect
add_filter('woocommerce_login_redirect', 'wcc_redirects', 9999, 2);
//I have added also WC registration redirect
add_filter('woocommerce_registration_redirect', 'wcc_redirects', 9999, 1);
//Then this will be the handler
function wcc_redirects ($redirect) {
if (isset($_COOKIE['nlcrc'])) {
$redirect = $_COOKIE['nlcrc'];
return $redirect;
} else {
$redirect = home_url();
return $redirect;
}
}
or you can also somewhat quick and dirty with Javascript. If your default login page is Woocommerce My Account Page.
add_filter('woocommerce_login_redirect', 'wc_cstm_login_redirect', 99 );
function wc_cstm_login_redirect () {
echo "<script type='text/javascript'>
history.go(-2);
</script>";
}
Please try the below code, i hope it helps you.
Paste the below code in current active theme functions.php file.
// start global session for saving the referer url
function start_session() {
if(!session_id()) {
session_start();
}
}
add_action('init', 'start_session', 1);
// get referer url and save it
function redirect_url() {
if (! is_user_logged_in()) {
$_SESSION['referer_url'] = wp_get_referer();
} else {
session_destroy();
}
}
add_action( 'template_redirect', 'redirect_url' );
//login redirect
function login_redirect() {
if (isset($_SESSION['referer_url'])) {
wp_redirect($_SESSION['referer_url']);
} else {
wp_redirect(home_url());
}
}
add_filter('woocommerce_login_redirect', 'login_redirect', 1100, 2);
We have to use WordPress referrer function:
For example, set referrer URL in session or hidden field by clicking on add to cart button or any button to store previous URL. Once login or register success add WooCommerce success login redirect to that URL.
Read about the Referrer function.
Here's an answer about the WooCommerce login redirect.
this will solve your prolem
add_filter( 'woocommerce_login_redirect', function(){
wp_safe_redirect(wp_get_referer());
}, 10, 2 );

Conditional function that check if products are already in cart in Woocommerce 3

Hi solution provided here WooCommerce - Check if item's are already in cart working perfect. This is the function code:
function woo_in_cart($arr_product_id) {
global $woocommerce;
$cartarray=array();
foreach($woocommerce->cart->get_cart() as $key => $val ) {
$_product = $val['product_id'];
array_push($cartarray,$_product);
}
if (!empty($cartarray)) {
$result = array_intersect($cartarray,$arr_product_id);
}
if (!empty($result)) {
return true;
} else {
return false;
};
}
Usage
$my_products_ids_array = array(22,23,465);
if (woo_in_cart($my_products_ids_array)) {
echo 'ohh yeah there some of that products in!';
}else {
echo 'no matching products :(';
}
But I need use as if(in_array) but no luck so far. What i doing wrong?
$my_products_ids_array = array("69286", "69287",);
if (in_array("69286", $my_products_ids_array)) {
echo '<p>' . the_field ( 'cart_field', 'option' ) . '</p>';
}
if (in_array("69287", $my_products_ids_array)) {
echo '<p>' . the_field ( 'cart_field-1', 'option' ) . '</p>';
}
Thank you
Your main function code is outdated.
For Advanced custom fields (ACF):
you need to use get_field() (that return the field value) instead of the_field() (that echo the field value).
You may need to add a product ID as 2nd argument in get_field('the_slug', $product_id ).
So try:
function is_in_cart( $ids ) {
// Initialise
$found = false;
// Loop Through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
// For an array of product IDS
if( is_array($ids) && ( in_array( $cart_item['product_id'], $ids ) || in_array( $cart_item['variation_id'], $ids ) ) ){
$found = true;
break;
}
// For a unique product ID (integer or string value)
elseif( ! is_array($ids) && ( $ids == $cart_item['product_id'] || $ids == $cart_item['variation_id'] ) ){
$found = true;
break;
}
}
return $found;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The custom conditional function is_in_cart( $ids ) accept a string (a unique product Id) or an array of product Ids.
Your revisited usage (ACF get_field may need a post ID (product ID)):
if ( is_in_cart( "69286" ) ) {
echo '<p>' . get_field ( 'cart_field' ) . '</p>'; // or get_field ( 'cart_field', "69286" )
}
if ( is_in_cart( "69287" ) ) {
echo '<p>' . get_field ( 'cart_field-1' ) . '</p>'; // or get_field ( 'cart_field', "69287" )
}

Categories