I am trying to send out emails to my customers and allow them one click to reset passwords with their email pre-filled on the reset password page by URL /account/lost-password/?email=123#gmail.com
However, I am not sure how to make it right. Here is my code. Thanks!
add_action( 'template_redirect', 'set_custom_data_wc_session' );
function set_custom_data_wc_session () {
if ( isset( $_GET['email'] ) ) {
$em = isset( $_GET['email'] ) ? esc_attr( $_GET['email'] ) : '';
// Set the session data
WC()->session->set( 'custom_data', array( 'email' => $em ) );
}
}
add_filter( 'woocommerce_login_form' , 'prefill_login_form' );
function prefill_login_form ( $fields ) {
// Get the session data
$data = WC()->session->get('custom_data');
// Email
if( isset($data['email']) && ! empty($data['email']) )
$fields['user_login']['default'] = $data['email'];
return $fields;
}
I managed to do it by referencing this thread
Pre-fill Woocommerce login fields with URL variables saved in session
<?php
add_action('woocommerce_lostpassword_form','woocommerce_js_2');
function woocommerce_js_2()
{ // break out of php
?>
<script>
// Setup a document ready to run on initial load
jQuery(document).ready(function($) {
//var r = /[?|&](\w+)=(\w+)+/g; //matches against a kv pair a=b
var r = /[?|&](\w+)=([\w.-]+#[\w.-]+)/g;
var query = r.exec(window.location.href); //gets the first query from the url
while (query != null) {
//index 0=whole match, index 1=first group(key) index 2=second group(value)
$("input[name="+ query[1] +"]").attr("value",query[2]);
query = r.exec(window.location.href); //repeats to get next capture
}
});
</script>
<?php } // break back into php
Related
I try to send a customized email template when a customer has a ticket (custom product type) in cart.
I have the following:
function bc_customer_completed_order_template($template, $template_name, $template_path)
{
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = wc_get_product( $cart_item['product_id'] );
$type = get_class($product);
if ( $type == 'WC_Product_Tickets' && 'customer-completed-order.php' === basename($template) ) {
$template = trailingslashit(plugin_dir_path( __FILE__ )) . 'templates/customer-completed-order.php';
}
}
return $template;
}
add_filter('woocommerce_locate_template', 'bc_customer_completed_order_template', 10, 3);
The conditionals are working (on cart and checkout page for example), but when the order is placed, the new template is not used.
Anybody?
Your email template will look like this:
Code snippets:
// Suppose orders don't have ticket products.
$has_tickets = false;
// Loop order items.
foreach ( $order->get_items() as $item_id => $item ) {
// Get product object from order item.
$_product = $item->get_product();
// Check if the product object is valid and the class is `WC_Product_Tickets`
if ( $_product && 'WC_Product_Tickets' === get_class( $_product ) ) {
// Change the flag.
$has_tickets = true;
// Break the loop as we alreay have true flag.
break;
}
}
// Check if order have tickets items.
if ( $has_tickets ) {
// Load custom email template.
wc_get_template( 'templates/custom-customer-completed-order.php' );
// Return as we don't need the below code.
return;
}
It turned out, although the above solution is correct in its idea, in reality one cannot load a template and make use of the $order without extending the woocommerce email class.
Therefore i loaded the function inside the email template itself and made an if - else statement so for situation A the layout is different then for situation b.
Like so:
$has_tickets = false;
// Loop order items.
foreach ( $order->get_items() as $item_id => $item ) {
// Get product object from order item.
$_product = $item->get_product();
// Check if the product object is valid and the class is `WC_Product_Tickets`
if ( $_product && 'WC_Product_Tickets' === get_class( $_product ) ) {
// Change the flag.
$has_tickets = true;
// Break the loop as we alreay have true flag.
break;
}
}
// Check if order have tickets items.
if ( $has_tickets ) {
do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
//custom email layout here//
}
else{
//Regular email template here
}
I am trying to check if a user meta data is empty or not. If empty, redirect the user to a page, else redirect to the default page.
But my following codes is only redirecting to the default page.
add_filter('woocommerce_login_redirect', 'ac_my_acct_login_redirect');
function ac_my_acct_login_redirect($redirect_to) {
$user_id = get_current_user_id();
$father = get_user_meta( $user_id, 'fath_name', true );
$update_pro = esc_url(get_permalink('123')); // the page I want for redirection if metadata is empty
$my_acct = esc_url(get_permalink( wc_get_page_id( 'myaccount' ) )); // default woocommerce my account page
if(empty($father)){
$redirect_to = $update_pro;
}
else {
$redirect_to = $my_acct;
}
return $redirect_to;
}
meta key = fath_name (even it has value, still the redirection is not working as intended). Any advice?
Your code contains some mistakes
get_current_user_id() is not necessary, as $user is passed to the callback function
get_permalink() expects an int (123), not a string ("123")
Make sure the page ID actually exists
So you get:
function filter_woocommerce_login_redirect( $redirect, $user ) {
// Get user meta
$value = get_user_meta( $user->ID, 'fath_name', true );
// Empty
if ( empty( $value ) ) {
$redirect = get_permalink( 123 );
} else {
// Get the "My account" url
$redirect = get_permalink( wc_get_page_id( 'myaccount' ) );
}
return $redirect;
}
add_filter( 'woocommerce_login_redirect', 'filter_woocommerce_login_redirect', 10, 2 );
I'm coming across an issue when trying to register a second user account once someone registers as a customer via WooCommerce. I have added the following woocommerce_created_customer hook:
add_action('woocommerce_created_customer', function($customer_id)
{
if(isset($_POST['second_user_first_name']) && isset($_POST['second_user_last_name']))
{
$createSecondUserId = wp_create_user(strtolower($_POST['second_user_first_name'].'-'.$_POST['second_user_last_name']).'-'.$customer_id, wp_generate_password(), 'test#test.com');
if(is_wp_error($createSecondUserId))
{
$errors = $createSecondUserId->errors;
print_r($errors);
die();
}
}
});
However I get the following error when submitting a new WooCommerce registration:
Array ( [existing_user_login] => Array ( [0] => Sorry, that username already exists! ) )
It's strange as I'm setting a random username within the wp_create_user function, so the usernames should not clash. Has anyone got any ideas?
You can use username_exists() to determines that the given username exists.
add_action( 'woocommerce_created_customer', function($customer_id){
if( isset( $_POST['second_user_first_name'] ) && isset( $_POST['second_user_last_name'] ) ) {
if( !username_exists( strtolower( $_POST['second_user_first_name'].'-'.$_POST['second_user_last_name'] ).'-'.$customer_id ) ){
$createSecondUserId = wp_create_user( strtolower( $_POST['second_user_first_name'].'-'.$_POST['second_user_last_name'] ).'-'.$customer_id, wp_generate_password(), 'test#test.com' );
if(is_wp_error($createSecondUserId)){
$errors = $createSecondUserId->errors;
print_r($errors);
die();
}
}
}
});
If the username already exists you can create a new one by adding a progressive numeric suffix. In this way you will be sure that the username of the second account will always be unique.
Note that if you run multiple tests with your current code you need to
make sure you remove the user with the email address test#test.com
otherwise you will get an error: [existing_user_email] => Sorry, that email address is already used!.
add_action('woocommerce_created_customer', function( $customer_id ) {
if ( isset($_POST['second_user_first_name']) && isset($_POST['second_user_last_name']) ) {
// create the username based on the form data
$username = strtolower( $_POST['second_user_first_name'] . '-' . $_POST['second_user_last_name'] ) . '-' . $customer_id;
// if the username already exists it creates a unique one
if ( username_exists($username) ) {
$i = 0;
while ( username_exists($username) ) {
$username = $username . '-' . ++$i;
}
}
// create the second user
$createSecondUserId = wp_create_user( $username, wp_generate_password(), 'test#test.com' );
}
});
The code has been tested and works. Add it to your active theme's functions.php.
I want a pop up message to appear when a user without a certain postal code tries to look at a certain category.
I have gotten as far as to redirect the user if there postal code is not in the allowed array.
I would just like it to state "You cannot access this category" and without any redirect.
function my_restrict_access() {
if ( is_product_category() ) {
$category = get_queried_object();
if ( $category ) {
$category_id = $category->term_id;
$allowed_category_id = array(3078, 3385);
if ( in_array($category_id, $allowed_category_id) ) {
if ( !is_user_logged_in() ) {
wp_redirect( '/' );
exit;
} else {
global $woocommerce;
$customer = new WC_Customer();
$customer_postcode = $woocommerce->customer->get_billing_postcode();
// uncomment line below for debug purposes, this will show you the postcode on the current page
//echo $customer_postcode;
$allowed_post_code = array(3610, 3626, 3650);
if ( !in_array($customer_postcode, $allowed_post_code) ) {
wp_redirect( '/' );
exit;
}
}
}
}
}
}
add_action( 'template_redirect', 'my_restrict_access');
You better need to use wp filter the_content to change front content...
add_action( 'the_content', 'restrict_user_to_certain_shop_category' );
function restrict_user_to_certain_shop_category( $content ){
global $woocommerce;
// list of all allowed woo product categories
$allowed_categories = array( 3078, 3385 );
// allowed user whose postcodes are following
$allowed_post_codes = array( 3610, 3626, 3650 );
// check if current viweing page is product archive page
if ( is_product_category() ) {
$current_category = get_queried_object();
// extract archive category id
$current_category_id = $current_category->term_id;
// check if current category is in allowed array list
if ( in_array( $current_category_id, $allowed_categories ) ) {
// check if user is not logged in
if ( ! is_user_logged_in() ) {
// message to show when user is not logged in and viewing allowed product category
$content = 'You cannot access this category';
}
// user is logged in and viewing allowed product category
else {
$customer = new WC_Customer();
$customer_postcode = $woocommerce->customer->get_billing_postcode();
// check if user is from allowed postarea
if ( !in_array( $customer_postcode, $allowed_post_codes ) ) {
// message to show when user is logged in and viewing allowed product category + from allowed postarea
$content = 'You cannot access this category';
}
}
}
}
return $content;
}
I am using add_action( 'after_setup_theme', 'custom_login' ); hook in one of my website for auto redirect user to his dashboard page.
Here is my code :---
function custom_login($username, $password='') {
$creds = array();
$creds['user_login'] = $username;
$creds['user_password'] = $password;
$creds['remember'] = true;
$user = wp_signon( $creds, false );
if ( is_wp_error($user) ){
echo $user->get_error_message();
}
}
// run it before the headers and cookies are sent
add_action( 'after_setup_theme', 'custom_login' );
Its working fine on old version, But now I have upgrade wordpress version and its creating problem with nonce.
Are you sure you want to do this?
Everytime this error display on the screen when I do anything like update plugin, theme and permalinks.
When I comment this code then website working fine except auto redirect functionality.
Here is my website url :- https://www.linearrecruitment.co.uk/
Please help me where I do mistake.
That's a normal behaviour - nonce is a token used by Wordpress to check the validity of the form in order to prevent CSRF attacks.
A valid login form in Wordpress should have an hidden input field generated with wp_nonce_field:
wp_nonce_field('my_login_form');
Then in the login function the token is checked with the wp_verify_nonce function:
if (!isset($_POST['my_login_form']) || !wp_verify_nonce($_POST['_wpnonce'], 'my_login_form')) {
die('Invalid form');
}
What you're trying to do (auto login) is done wrong as add_action doesn't send any parameter for the after_setup_theme hook, so your username is probably empty. I don't know how this could possibly work before, maybe it managed to log in somehow with an empty username.
I suggest you to declare some globals vars for your username and password, as it seems to be static inputs:
global $username, $password;
$username = 'my_login';
$password = 'my_password';
And then on the beginning of your function import those globals with:
global $username, $password;
So what about the nonce?
On the last versions of Wordpress, the check_admin_referer have changed a bit, from:
function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
if ( -1 == $action )
_doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2' );
$adminurl = strtolower(admin_url());
$referer = strtolower(wp_get_referer());
$result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
if ( !$result && !(-1 == $action && strpos($referer, $adminurl) === 0) ) {
wp_nonce_ays($action);
die();
}
do_action( 'check_admin_referer', $action, $result );
return $result;
}
To :
function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
if ( -1 == $action )
_doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2' );
$adminurl = strtolower(admin_url());
$referer = strtolower(wp_get_referer());
$result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
do_action( 'check_admin_referer', $action, $result );
if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
wp_nonce_ays( $action );
die();
}
return $result;
}
As you can see they moved the check_admin_referer hook - now we can change the value of $result before the wp_nonce_ays function (the one that display the message you try to get rid of) as been called.
That mean we could add the following hook in the theme functions.php in order to force the nonce validation:
add_action( 'check_admin_referer', array('custom_check_admin_referer' ) );
function custom_check_admin_referer() {
return 1;
}
That should work around your problem, but you must be aware that this could possibly be a security issue - you maybe want to do more test in that function before returning 1.