WooCommerce Session Variables Initialization - php

I'm trying to create a session variable in shop page and then I want to show this variable values in checkout page.
I wrote this code in woocommerce function page:
// Creating session variables
add_action( 'template_redirect', 'oturum_degiskeni_olustur' );
function oturum_degiskeni_olustur () {
if ( isset( $_GET['konumu'] ) || isset( $_GET['masa_no'] ) ) {
$konum = isset( $_GET['konumu'] ) ? esc_attr( $_GET['konumu'] ) : '';
$masa = isset( $_GET['masa_no'] ) ? esc_attr( $_GET['masa_no'] ) : '';
// Set the session data
WC()->session->set( 'custom_data', array( 'konum' => $konum, 'masa' => $masa ) );
}
}
// Show session variables in checkout page
add_action('woocommerce_before_checkout_form', 'yeni_alanlar');
function yeni_alanlar($checkout){
$data = WC()->session->get('custom_data');
echo '<div id="custom_checkout_field">';
if( isset($data['konum']) && ! empty($data['konum']) && isset($data['masa']) && ! empty($data['masa']) ){
echo '<p><strong>Konumunuz : </strong>' . $data['konum'] .'<br/><strong>Masanız : </strong>' . $data['masa'] .'</p>';
}
echo '</div>';
}
URL for session variables: www.domain.com/shop/?konumu=newyork&masa_no=12
But this code working when user's second visit.
For example; user use this custom URL and visit the shop page and continue to cart and checkout page. But, my code is not working. Then, user going to this custom URL again and continue to cart & checkout page and code is working this time.
It is not working when first visit.
Why is that? How can I solve this issue?

You need to early init customer session, so we will change template_redirect to init hook using the WC_Session_Handler method set_customer_session_cookie() like:
// Creating session variables
add_action( 'init', 'oturum_degiskeni_olustur' );
function oturum_degiskeni_olustur () {
// Early initialize customer session
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
if ( isset( $_GET['konumu'] ) && isset( $_GET['masa_no'] ) ) {
$konum = isset( $_GET['konumu'] ) ? esc_attr( $_GET['konumu'] ) : '';
$masa = isset( $_GET['masa_no'] ) ? esc_attr( $_GET['masa_no'] ) : '';
// Set the session data
WC()->session->set( 'custom_data', array( 'konum' => $konum, 'masa' => $masa ) );
}
}
// Show session variables in checkout page
add_action('woocommerce_before_checkout_form', 'yeni_alanlar');
function yeni_alanlar(){
if( ( $data = WC()->session->get('custom_data') )
&& isset($data['konum']) && isset($data['masa']) ) {
echo '<div id="custom_checkout_field">
<p><strong>Konumunuz : </strong>' . $data['konum'] .'<br/>
<strong>Masanız : </strong>' . $data['masa'] .'</p>
</div>';
}
}
Now it should better work.

Related

Pre-fill WooCommerce billing fields with string url

I have a Wordpress site with WooCommerce webshop and a client (hotel) that wants customers to order products in my webshop. I want those customers not to have to fill in the hotel information during checkout (the products are delivered to their room).
I have build a custom page for the hotel where people can place certain products in the cart, and when they want to checkout they press a custom checkout button that prefills the checkout fields. I am using this technique to achieve this: https://newpulselabs.com/prefill-checkout-fields-cartflows/
// Autofill checkout fields from URL
add_filter( 'woocommerce_checkout_fields' , 'prefill_billing_fields' );
function prefill_billing_fields ( $address_fields ) {
// Get the data from the URL
if ( isset( $_GET['fname'] ) || isset( $_GET['lname'] ) || isset( $_GET['email'] ) || isset( $_GET['company'] ) )
{
// wp_die();
$fname = isset( $_GET['fname'] ) ? esc_attr( $_GET['fname'] ) : '';
$lname = isset( $_GET['lname'] ) ? esc_attr( $_GET['lname'] ) : '';
$em = isset( $_GET['email'] ) ? esc_attr( $_GET['email'] ) : '';
$company = isset( $_GET['company'] ) ? esc_attr( $_GET['company'] ) : '';
// First Name
if( isset($_GET['fname']) && ! empty($_GET['fname']) ){
if( isset( $address_fields['billing']['billing_first_name'] ) ){
$address_fields['billing']['billing_first_name']['default'] = $fname;
}
}
// Last Name
if( isset($_GET['lname']) && ! empty($_GET['lname']) ){
if( isset( $address_fields['billing']['billing_last_name'] ) ){
$address_fields['billing']['billing_last_name']['default'] = $lname;
}
}
// Email
if( isset($_GET['email']) && ! empty($_GET['email']) ){
if(isset( $address_fields['billing']['billing_email'] )){
$address_fields['billing']['billing_email']['default'] = $em;
}
}
// Company
if( isset($_GET['company']) && ! empty($_GET['company']) ){
if(isset( $address_fields['billing']['billing_company'] )){
$address_fields['billing']['billing_company']['default'] = $company;
}
}
}
return $address_fields;
}
The url looks like this:
https://www.yourweburl.com/checkout-page/?email=name#example.com&fname=John&lname=Smith&company=ABC Company
And it works perfectly… for new visitors. If a visitor happened to have ordered before in the webshop (and used a different billing address) then that is stored locally in the browser and auto filled.
This technique will not overwrite existing/previous autofill values. I think because it is checking if the cell is empty or not:
if( isset($_GET['fname']) && ! empty($_GET['fname']) ){
if( isset( $address_fields['billing']['billing_first_name'] ) ){
$address_fields['billing']['billing_first_name']['default'] = $fname;
}
}
I tried disabling autofill on the checkout page with this:
add_filter('woocommerce_checkout_get_value','__return_empty_string', 1, 1);
Again that works so well that it removes all prefilled text. So it also removes the information I want to prefill. It works too good ;)
I prefer to alter the first code so that it always overwrites existing values, regardless of what is stored in the browser.
Can anyone help point me in the right direction of how to change the code?
Thanks a lot!
Koen

Is there a way to make redirect work, instead of going back to form page after clicking browser's back button in PHP/WordPress?

I have a little problem. I created a form on a page, which sends data with $_POST. Data is being checked for errors and, if there are any, the page is going back to form with errors displayed. Errors are being get from $_POST variable. If I eventually input correct data I'm being redirected to homepage. But if I click the back button I can see the form again with the submission error (previously get from $_POST). Is it possible to go back but see homepage instead of login form with errors?
What's more, that situation doesn't happen when I input correct data straight away. If that happens, after clicking back button, no form visible, only homepage. Form (after clicking back button) is visible only if I input incorrect data first and the correct data.
This is in WordPRess, so you can see some WP related stuff in the code below.
Here is the login form:
echo 'Login Form';
$tw_email_err = '';
$tw_email = '';
$tw_form = tw_login_process(); // This function is below. It processes the form input.
$tw_email = $tw_form['email'];
$tw_email_err = $tw_form['message'];
$tw_consent_err = $tw_form['consent_msg'];
echo '<h2>Form</h2>
<form method="post">';
wp_nonce_field( 'tw_login_form', 'tw_login_nonce' );
echo '<input type="text" placeholder="e-mail" name="tw_email" value="' . esc_attr( $tw_email ) . '">
<span class="tw-error">* ' . esc_html( $tw_email_err ) . '</span>
<br><br>
<input type="checkbox" id="tw_consent_check" name="tw_consent" value="on">
<label for="tw_consent_check">Zgoda</label><br>
<span class="tw-error">* ' . esc_html( $tw_consent_err ) . '</span>
<br><br>
<p><span class="error">* required field</span></p>
<input type="submit" name="submit" value="Submit">
</form>';
Form processing:
function tw_login_process() {
$trzywu_users = tw_get_users(); // Get saved users from database, works OK.
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) {
$tw_check_email = ( isset( $_POST['tw_email'], $_POST['tw_login_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['tw_login_nonce'] ), 'tw_login_form' ) )
? sanitize_text_field( wp_unslash( $_POST['tw_email'] ) )
: '';
$tw_check_consent = ( isset( $_POST['tw_consent'], $_POST['tw_login_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['tw_login_nonce'] ), 'tw_login_form' ) )
? sanitize_text_field( wp_unslash( $_POST['tw_consent'] ) )
: '';
if ( $tw_check_email ) {
$tw_check_result['email'] = $tw_check_email;
if ( $trzywu_users && filter_var( $tw_check_email, FILTER_VALIDATE_EMAIL ) && in_array( $tw_check_email, $trzywu_users, true ) ) {
$tw_check_result['check'] = 'valid_existent';
$tw_check_result['message'] = '';
} elseif ( ! filter_var( $tw_check_email, FILTER_VALIDATE_EMAIL ) ) {
$tw_check_result['check'] = 'not_valid';
$tw_check_result['message'] = 'Nieprawidłowy format adresu e-mail.';
} elseif ( ! $trzywu_users || ! in_array( $tw_check_email, $trzywu_users, true ) ) {
$tw_check_result['check'] = 'not_existent';
$tw_check_result['message'] = 'Adres e-mail nie jest zarejestrowany.';
}
} else {
$tw_check_result['email'] = '';
$tw_check_result['check'] = 'not_set';
$tw_check_result['message'] = 'Podaj adres e-mail';
}
$tw_check_result['consent'] = 'on' === $tw_check_consent ? 'consent_granted' : 'no_consent';
if ( 'on' === $tw_check_consent ) {
$tw_check_result['consent'] = 'consent_granted';
$tw_check_result['consent_msg'] = '';
} else {
$tw_check_result['consent'] = 'no_consent';
$tw_check_result['consent_msg'] = 'Wyraź zgodę na warunki Polityki Prywatności.';
}
return $tw_check_result;
}
}
And finally redirections:
function tw_user_redirect() {
global $tw_cookie_name; // This is cookie name for setcookie, don't worry about that.
header( 'Cache-Control: no cache' ); // I'm using this to eliminate form resubmission error. Is it OK?
session_cache_limiter( 'private_no_expire' );
session_start();
$tw_result = tw_login_process(); //That's above form's processing.
$tw_users = tw_get_users(); // Just additional check, works OK.
$tw_login_page = tw_get_login_page_id(); //this function gets login page ID, it works OK.
if ( 'consent_granted' === $tw_result['consent'] && 'valid_existent' === $tw_result['check'] ) {
if ( in_array( $tw_result['email'], $tw_users, true ) ) {
$cokie_session_value = tw_password_hash( $tw_result['email'] );
$_SESSION['user'] = $cokie_session_value;
setcookie( $tw_cookie_name, $cokie_session_value, time() + ( 86400 * 7 ), '/' ); //Not important, I suppose?
}
wp_safe_redirect( home_url() );
exit;
}
// This somehow doesn't work after clicking back button. It works in any other scenario though.
if ( isset( $_SESSION['user'] ) && is_page( $tw_login_page ) ) {
wp_safe_redirect( home_url() );
exit;
// This works as expected.
} elseif ( ! isset( $_SESSION['user'] ) && ! is_page( $tw_login_page ) ) {
wp_safe_redirect( get_permalink( $tw_login_page ) );
exit;
}
}
add_action( 'template_redirect', 'tw_user_redirect' );

Save WooCommerce custom Session Variables as order meta data

I'm trying to store custom session variables in database. Then, show them inside new order email and order details in WooCommerce Admin.
I have custom variables inside session:
add_action( 'init', 'oturum_degiskeni_olustur' );
function oturum_degiskeni_olustur () {
// Early initialize customer session
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
if ( isset( $_GET['konumu'] ) || isset( $_GET['masa_no'] ) ) {
$konum = isset( $_GET['konumu'] ) ? esc_attr( $_GET['konumu'] ) : '';
$masa = isset( $_GET['masa_no'] ) ? esc_attr( $_GET['masa_no'] ) : '';
// Set the session data
WC()->session->set( 'custom_data', array( 'konum' => $konum, 'masa' => $masa ) );
}
}
Firstly, I added custom variables to database with this code;
// Storing session variables for using them in order notifications
add_action( 'woocommerce_checkout_create_order', 'oturum_degiskeni_kaydet' );
function oturum_degiskeni_kaydet( $order, $data ) {
if ( $_POST['konumu'] ) update_meta_data( $order_id, '_konum', esc_attr( $_POST['konumu'] ) );
if ( $_POST['masa_no'] ) update_meta_data( $order_id, '_masa', esc_attr( $_POST['masa_no'] ) );
}
Second, I added this variable's data to a new order email for admin.
// Show this session variables in new order email for admin
add_action( 'woocommerce_email_after_order_table', 'konumu_emaile_ekle', 20, 4 );
function konumu_emaile_ekle( $order, $sent_to_admin, $plain_text, $email ) {
if ( get_post_meta( $order->get_id(), '_konum', true ) ) echo '<p><strong>Konum :</strong> ' . get_post_meta( $order->get_id(), '_konum', true ) . '</p>';
if ( get_post_meta( $order->get_id(), '_masa', true ) ) echo '<p><strong>Masa Numarası :</strong> ' . get_post_meta( $order->get_id(), '_masa', true ) . '</p>';
}
Last part of the code is shown session variables data in WooCommerce order page;
// Show session variable in woocommerce order page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'konumu_admine_ekle', 10, 1 );
function konumu_admine_ekle( $order ) {
$order_id = $order->get_id();
if ( get_post_meta( $order_id, '_konum', true ) ) echo '<p><strong>Konum :</strong> ' . get_post_meta( $order_id, '_konum', true ) . '</p>';
if ( get_post_meta( $order_id, '_masa', true ) ) echo '<p><strong>Masa Numarası :</strong> ' . get_post_meta( $order_id, '_masa', true ) . '</p>';
}
But, it does not work. When customer made an order, it gave an error "We were unable to process your order, please try again."
Updated: There are some mistakes in your code when you are trying to save your custom data from session as order meta data and display it on emails and admin order pages…
Your first function is correct (oturum_degiskeni_olustur)…
Assuming that data is passed through URL like: website.com/?konumu=newyork&masa_no=12
Here is the revisited code:
// Unchanged
add_action( 'init', 'oturum_degiskeni_olustur' );
function oturum_degiskeni_olustur () {
// Early initialize customer session
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
if ( isset( $_GET['konumu'] ) || isset( $_GET['masa_no'] ) ) {
$konum = isset( $_GET['konumu'] ) ? esc_attr( $_GET['konumu'] ) : '';
$masa = isset( $_GET['masa_no'] ) ? esc_attr( $_GET['masa_no'] ) : '';
// Set the session data
WC()->session->set( 'custom_data', array( 'konum' => $konum, 'masa' => $masa ) );
}
}
// Save custom session data as order meta data
add_action( 'woocommerce_checkout_create_order', 'oturum_degiskeni_kaydet' );
function oturum_degiskeni_kaydet( $order ) {
$data = WC()->session->get( 'custom_data' ); // Get custom data from session
if ( isset($data['konum']) ) {
$order->update_meta_data( '_konum', $data['konum'] );
}
if ( isset($data['masa']) ) {
$order->update_meta_data( '_masa', $data['masa'] );
}
WC()->session->__unset( 'custom_data' ); // Remove session variable
}
// Show this session variables in new order email for admin and in woocommerce order page
add_action( 'woocommerce_email_after_order_table', 'konumu_emaile_admine_ekle', 20 );
add_action( 'woocommerce_admin_order_data_after_billing_address', 'konumu_emaile_admine_ekle' );
function konumu_emaile_admine_ekle( $order ) {
if ( $konum = $order->get_meta( '_konum' ) )
echo '<p><strong>Masa Numarası :</strong> ' . $konum . '</p>';
if ( $masa = $order->get_meta( '_masa' ) )
echo '<p><strong>Konum :</strong> ' . $masa . '</p>';
}
Code goes in functions.php file of your active child theme (or active theme). Tested and Works.
On the email notification before customer details:
On admin order edit page (under billing phone):
Tested on WooCommerce 4.2+ under storefront theme

Customize Order received page based on shipping method in WooCommerce

How could I customise the order thank you page based on the order's shipping method? So for example if a customer used 'Delivery on request' option, the thank you page would display a different title.
add_filter( 'the_title', 'woo_personalize_order_received_title', 10, 2 );
function woo_personalize_order_received_title( $title, $id ) {
if ( is_order_received_page() && get_the_ID() === $id ) {
global $wp;
// Get the order. Line 9 to 17 are present in order_received() in includes/shortcodes/class-wc-shortcode-checkout.php file
$order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
$order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key ) {
$order = false;
}
}
if ( isset ( $order ) ) {
$chosen_titles = array();
$available_methods = $wp->shipping->get_packages();
$chosen_rates = ( isset( $wp->session ) ) ? $wp->session->get( 'chosen_shipping_methods' ) : array();
foreach ($available_methods as $method)
foreach ($chosen_rates as $chosen) {
if( isset( $method['rates'][$chosen] ) ) $chosen_titles[] = $method['rates'][ $chosen ]->label;
}
if( in_array( 'Delivery price on request', $chosen_titles ) ) {
//$title = sprintf( "You are awesome, %s!", esc_html( $order->billing_first_name ) ); // use this for WooCommerce versions older then v2.7
$title = sprintf( "You are awesome, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
}
return $title;
}
is_order_received_page() doesn't exist. Instead use is_wc_endpoint_url( 'order-received' )…
Also $wp->session or $wp->shipping will not work. Instead you can find the chosen shipping method data in the order item "shipping".
Try this instead:
add_filter( 'the_title', 'customizing_order_received_title', 10, 2 );
function customizing_order_received_title( $title, $post_id ) {
if ( is_wc_endpoint_url( 'order-received' ) && get_the_ID() === $post_id ) {
global $wp;
$order_id = absint( $wp->query_vars['order-received'] );
$order_key = isset( $_GET['key'] ) ? wc_clean( $_GET['key'] ) : '';
if ( empty($order_id) || $order_id == 0 )
return $title; // Exit
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key )
return $title; // Exit
$method_title_names = array();
// Loop through Order shipping items data and get the method title
foreach ($order->get_items('shipping') as $shipping_method )
$method_title_names[] = $shipping_method->get_name();
if( in_array( 'Delivery price on request', $method_title_names ) ) {
$title = sprintf( "You are awesome, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
return $title;
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
Similar: Adding custom message on Thank You page by shipping method in Woocommerce

login authentication control on button for PHP

Need to set a login control on a button for my wp website. Button's code appears to be like this:
$enable_redirect = get_field('redirect_to_offer') ? get_field('redirect_to_offer') : array('');
echo'' . fw_ssd_get_option('show-code-text') . '';
}
My goal is to check if the user who clicks on that button is logged in or not with:
if ( function_exists('um_profile_id') && !um_profile_id() && get_field('registered_members_only') ) {
wp_redirect(home_url('login/'));
exit;
}
But I couldn't figure out where should I put the controller code. F1 please.
Since your button URL is external, changing the button URL from the beginning seems to be a better option (as discussed on the comments):
$enable_redirect = get_field( 'redirect_to_offer' ) ? get_field('redirect_to_offer') : array( '' );
if ( function_exists( 'um_profile_id' ) && ! um_profile_id() && get_field( 'registered_members_only' ) ) {
$button_url = home_url( 'login/' );
} else {
$button_url = get_field( 'url' );
}
echo sprintf( '%4$s'
esc_url( $button_url ),
esc_attr( get_field( 'coupon_code' ) ),
esc_attr( $enable_redirect[0] ),
fw_ssd_get_option( 'show-code-text' )
);
The login status defines the final button URL.
Note: I used placeholder replacement with sprintf() in other to make it easier to read.

Categories