Customer Account Number for WooCommerce - woocommerce

In WooCommerce, from "Adding a hidden fields to checkout and process it through order" answer thread, which generates a verification number on checkout for orders,
I am trying to figure out how to turn this into a account number instead by which I mean:
when the customer registers, a unique number is generated
that number is saved to the account
the number can be displayed used echo later on
This is what I have tried so far (without success) =>
OPTION 1:
add_action( 'woocommerce_register_form_start', 'user_account_nr' );
function user_account_nr() {
$billing_account_number = '';
if ( isset( $_POST['billing_account_number'] ) ) {
$billing_account_number = $_POST['billing_account_number'];
}
?>
<p class="form-row form-row-first">
<input type="hidden" class="input-hidden" name="billing_account_number" id="reg_billing_account_number" value="<?php if ( ! empty( $_POST['billing_account_number'] ) ) esc_attr_e( $billing_account_number ); ?>" />
</p>
<div class="clear"></div>
<?php
}
add_action('woocommerce_created_customer', 'add_account_number');
function add_account_number($user_id)
{
$accountnumber = wp_rand(10000,99999);
update_user_meta($user_id, 'billing_account_number', $accountnumber);
}
OPTION 2:
add_action('user_register','aacount_on_user_register');
function account_on_user_register($user_id){
$last_name = $_POST['last_name'];
if ( isset($last_name) ){
$account_id = wp_rand(10000,99999) . $user_id;
add_user_meta( $user_id, 'account_id', $account_id);
}
}
/* Add user "account_id" meta when user registers */
add_action('woocommerce_created_customer', 'admin_email_on_registration', 10 , 1);
function admin_email_on_registration($user_id) {
$user = wp_get_current_user();
$last_name = $user->last_name;
if ( isset($last_name) ){
$account_id = wp_rand(10000,99999) . $user_id;
add_user_meta( $user_id, 'account_id', $account_id);
}
}
Here is a third option I was trying to make work:
function uuid() {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
add_action('woocommerce_created_customer', 'generate_unique_id_after_user_created', 10, 3);
function generate_unique_id_after_user_created( $user_id, $form_id,$sub_id ) {
if( !empty( $user_id ) ) {
$user_data = array(
'ID' => $user_id,
'user_login' => uuid(),
'user_email' => '',
);
$updated_user_id = wp_update_user( $user_data );
if ( is_wp_error( $updated_user_id ) ) {
// There was an error, probably that user doesn't exist.
} else {
// Success!
}
}
}

Related

Verifying Userprofile "Uniqueness" of Meta Value at the time of creation for wordpress user custom field meta-key "association_id"

I have a custom user profile field "association_id". I can see the field the underlying wordpess db table (usermeta) with the 'meta_key' as "association_id" and the 'meta_value' whatever that I maintain for each user.
add_action( 'show_user_profile', 'rudr_profile_fields' );
add_action( 'edit_user_profile', 'rudr_profile_fields' );
function rudr_profile_fields( $user )
{
// let's get custom field values
$association_id = get_user_meta( $user->ID, 'association_id', true );
?>
<h3>Association Information</h3>
<table class="form-table">
<tr>
<th><label for="association_id">Association_ID</label></th>
<td>
<input type="text" name="association_id" id="association_id" value="<?php echo esc_attr( $association_id ) ?>" class="regular-text" />
<span class="description"><?php _e("Please enter your Association ID (For eg. if RCIC, your license number)."); ?></span>
</td>
</tr>
</table>
<?php
}
//avoid self to edit //
//add_action( 'personal_options_update', 'rudr_save_profile_fields' ); //
add_action( 'edit_user_profile_update', 'rudr_save_profile_fields' );
function rudr_save_profile_fields( $user_id ) {
if( ! isset( $_POST[ '_wpnonce' ] ) || ! wp_verify_nonce( $_POST[ '_wpnonce' ], 'update-user_' . $user_id ) ) {
return;
}
if( ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
/* HOLDING SPACE FOR ENHANCED SNIPPED */
//include in the list view of users
add_filter( 'manage_users_columns', 'column_register_association_id' );
add_filter( 'manage_users_custom_column', 'column_display_association_id', 10, 3 );
function column_register_association_id( $columns )
{
$columns['association_id'] = 'association_id';
return $columns;
}
function column_display_association_id( $value, $column_name, $user_id )
{
$user_info = get_user_meta( $user_id, 'association_id', true );
if($column_name == 'association_id') return $user_info;
return $value;
}
//Sort association_id column
function association_id_register_sortable( $columns ) {
$columns['association_id'] = 'association_id';
return $columns;
}
add_filter( 'manage_users_sortable_columns', 'association_id_register_sortable' );
function association_id_orderby( $vars ) {
if ( isset( $vars['orderby'] ) && 'association_id' == $vars['orderby'] ) {
$vars = array_merge( $vars, array(
'meta_key' => 'association_id',
'orderby' => 'meta_value'
) );
}
return $vars;
}
add_filter( 'request', 'association_id_orderby' );
The preceding works fine and creates a meta key for storing meta value in the metadata wp table.
I want this custom user profile field value that I enter in the user admin page to be unique, verifying with the underlying wordpress database table. So I enhanced the code at the time of creation with the additional lines below. I tried these two snippets in the wordpress child theme, but it throws a critical error. I am on PHP version 8.
I tried two options below at the placeholder location in the above code, replacing the line below.
/* HOLDING SPACE FOR ENHANCED SNIPPED */
Option 1 that I tried.
$checkMeta=$wpdb->get_results("SELECT user_id FROM $wpdb->usermeta WHERE meta_key='association_id' AND meta_value=".$association_id,ARRAY_A);
if (empty($checkMeta)) {
update_user_meta( $user_id, 'association_id', sanitize_text_field( $_POST[ 'association_id' ] ) );
}
Option 2 that I tried.
$mysqli = new mysqli(SERVER, DBUSER, DBPASS, DATABASE); $result = $mysqli->query("SELECT user_id FROM usermeta WHERE meta_key='association_id' && meta_value=$association_id "); if($result->num_rows == 0) { // row not found, do stuff update_user_meta( $user_id, 'association_id', sanitize_text_field( $_POST[ 'association_id' ] ) ); } else { // row found, do stuff echo ' This ID is already used.'; } $mysqli->close();
Both failed to activate when I tried to create or change the 'association_field' value, throwing critical errors and aborting.

WooCommerce Shortcode For "Order Again" Customer's Last Order

I'm fairly new with this, but I am learning. I am trying to create a shortcode which can be inserted anywhere on the site, allowing the customer to order their previous order again.
In other words, I need to enable the customer to "order again" their last order. Main problem is, when I try this, the site goes blank (white screen).
Any ideas what's wrong here?
add_shortcode( 'order_again', 'matt_order_again' );
function matt_order_again( $order ) {
if ( is_user_logged_in() ) {
$user_id = get_current_user_id();
$customer = new WC_Customer( $user_id );
$last_order = $customer->get_last_order();
if ( $last_order->has_status( 'completed' ) ) {
$actions['order-again'] = array(
'url' => wp_nonce_url( add_query_arg( 'order_again', $order->get_id(), wc_get_cart_url() ), 'woocommerce-order_again' ),
'name' => __( 'Order again', 'woocommerce' ),
);
}
return $actions;
}
}
I have tried adding the global variable for WC.
try this :
add_shortcode( 'order_again', 'matt_order_again' );
function matt_order_again( $order ) {
if ( is_user_logged_in() ) {
$user_id = get_current_user_id();
$customer = new WC_Customer( $user_id );
$last_order = $customer->get_last_order();
if ( $last_order->has_status( 'completed' ) ) {
$actions['order-again'] = array(
'url' => wp_nonce_url( add_query_arg( 'order_again', $last_order->get_id(), wc_get_cart_url() ), 'woocommerce-order_again' ),
'name' => __( 'Order again', 'woocommerce' ),
);
}
return $actions;
}
}
Or if you want to return a button with url for order again using shorcode use this code (edited).
add_shortcode('order_again', 'matt_order_again');
function matt_order_again($order)
{
if (is_user_logged_in()) {
global $woocommerce;
ob_start();
$user_id = get_current_user_id();
$customer = new WC_Customer($user_id);
$last_order = $customer->get_last_order();
if(!$last_order){
return;
}
if ($last_order->has_status('completed')) {
$url = wp_nonce_url(add_query_arg('order_again', $last_order->get_id(), wc_get_cart_url()), 'woocommerce-order_again');
echo '' . __('Order Again', 'woocomerce') . '';
}
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
}

Complicated Woocommerce shipping Rules issue

I am trying to apply complicated shipping rules in Woocommerce.
I have basic products which is:
Spend
Shipping cost
less than 300
30$
300 or more
Free
But I also have some large products and products with special delivery requirements
product
Shipping Class
cost
large box
Truck with crane
1000$
large Box
Truck only
200$
Gazebo (Choice1: Delivery Only)
Delivery & Assebly
200$
Gazebo (Choice2: Delivery & Assembly)
Delivery & Assebly
350$
Below is my shipping methods
Shipping Methods
Standerd rates
Shipping With Assembly
For basic products everything is working well,
Also for large boxes its well as it shows in Standard shipping.
But when I add the (shipping with assembly) shipping method it still appear as choice even if no product with this class is in the cart.
I just need it to appear only when gazebo is in the cart
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_class_is_in_cart', 100, 2 );
function hide_shipping_when_class_is_in_cart( $rates, $package ) {
$free_shipping_method = 'free_shipping:13';
$shipping_classes = array('truck-crane','large-furniture','furniture-assembly');
$class_exists = false;
$cart_classes = array();
$shipping_methods = $shipping_zone->get_shipping_methods();
foreach( $package['contents'] as $cart_item )
$cart_item_class = $cart_item['data']->get_shipping_class();
if( in_array($cart_item_class , $shipping_classes ) ) {//Check if any shipping class exist
array_push($cart_classes,$cart_item_class); //push cart classes to array
$class_exists = true;
//break;
}
foreach($shipping_methods as $method){
$method_classes = $method->get_shipping_classes();
//Here i want to unset shipping methods which has no avaiable class in cart items
}
if( $class_exists )
unset( $rates[$free_shipping_method] );
return $rates;
}
I ended up adding the service like 'assembly' as a choice that comes with the product
my code below
/**
** Display Fields
*/
add_action('woocommerce_product_options_shipping', 'woocommerce_product_custom_product_service');
function woocommerce_product_custom_product_service()
{
global $woocommerce, $post;
echo '<div class="product_custom_field"><span class="wrap">';
woocommerce_wp_text_input(
array(
'id' => '_custom_product_service_label',
'placeholder' => 'Service Label',
'label' => __('Custom Service', 'woocommerce'),
)
);
woocommerce_wp_text_input(
array(
'id' => '_custom_product_service_fees',
'placeholder' => 'Service Fees',
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
echo '</span></div>';
}
/**
** Save Fields
*/
add_action('woocommerce_process_product_meta', 'woocommerce_product_custom_product_service_save');
function woocommerce_product_custom_product_service_save($post_id)
{
$woocommerce_custom_product_service_label = $_POST['_custom_product_service_label'];
$woocommerce_custom_product_service_fees = $_POST['_custom_product_service_fees'];
if (!empty($woocommerce_custom_product_service_label) && !empty($woocommerce_custom_product_service_fees)){
update_post_meta($post_id, '_custom_product_service_label', esc_attr($woocommerce_custom_product_service_label));
update_post_meta($post_id, '_custom_product_service_fees', esc_attr($woocommerce_custom_product_service_fees));
}elseif(empty($woocommerce_custom_product_service_label) && empty($woocommerce_custom_product_service_fees)){
update_post_meta($post_id, '_custom_product_service_label', '');
update_post_meta($post_id, '_custom_product_service_fees', '');
}
}
/**
** Product page form
*/
add_action('woocommerce_single_product_summary','add_custom_product_service_to_single_product', 2 );
function add_custom_product_service_to_single_product(){
global $product;
if( !$product->get_meta( '_custom_product_service_label' ) && !$product->get_meta( '_custom_product_service_fees' )) return;
add_action('woocommerce_before_add_to_cart_button', 'add_custom_product_service_option', 30 );
}
function add_custom_product_service_option(){
global $product;
$active_price = (float) $product->get_price();
$service_label = $product->get_meta( '_custom_product_service_label' );
$service_price = (float) $product->get_meta( '_custom_product_service_fees' );
$service_price_html = strip_tags( wc_price( wc_get_price_to_display( $product, array('price' => $service_price ) ) ) );
$active_price_html = wc_price( wc_get_price_to_display( $product ) );
$disp_price_sum_html = wc_price( wc_get_price_to_display( $product, array('price' => $active_price + $service_price ) ) );
echo '<div class="hidden-field">
<p class="form-row form-row-wide" id="service_option_field" data-priority="">
   <span class="woocommerce-input-wrapper"><label class="checkbox"> ' .$service_label.' '.__("Service:", "Woocommerce") .
' <input type="checkbox" class="input-checkbox " name="service_option" id="service_option" value="1"> +' . $service_price_html .
'</label></span></p>
<input type="hidden" name="service_price" value="' . $service_price . '">
<input type="hidden" name="active_price" value="' . $active_price . '"></div>';
// Jquery: Update displayed price
?>
<script type="text/javascript">
jQuery(function($) {
var cb = 'input[name="service_option"]'
pp = 'p.price';
// On change / select a variation
$('form.cart').on( 'change', cb, function(){
if( $(cb).prop('checked') === true )
               $(pp).html('<?php echo $disp_price_sum_html.__("(Assembly Included)", "Woocommerce"); ?>');
else
$(pp).html('<?php echo $active_price_html; ?>');
})
});
</script>
<?php
}
/**
** Add to Cart
*/
add_filter('woocommerce_add_cart_item_data', 'add_custom_product_service_data', 10, 3);
function add_custom_product_service_data( $cart_item_data, $product_id, $variation_id ) {
if (isset($_POST['service_option']) && !empty($_POST['service_option'])) {
$cart_item_data['new_price'] = (float) ($_POST['active_price'] + $_POST['service_price']);
$cart_item_data['service_price'] = (float) $_POST['service_price'];
$cart_item_data['active_price'] = (float) $_POST['active_price'];
foreach(WC()->cart->get_cart() as $cart_item){
if(($product_id == $cart_item['product_id']) && !empty($cart_item['service_price'])){
$unique_key = $cart_item['unique_key'];
break;
}
}
if(!empty($unique_key)){
$cart_item_data['unique_key'] = $unique_key;
}else{
$cart_item_data['unique_key'] = md5(microtime().rand());
}
return $cart_item_data;
}}
/**
** Set the new calculated cart item price
*/
add_action('woocommerce_before_calculate_totals', 'add_custom_product_service_custom_price', 20, 1);
function add_custom_product_service_custom_price($cart) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
foreach($cart->get_cart() as $cart_item) {
if (isset($cart_item['new_price']))
$cart_item['data']->set_price((float) $cart_item['new_price']);
}
}
/**
** Display in Cart
*/
add_filter('woocommerce_get_item_data', 'display_custom_product_service_item_data', 10, 2);
function display_custom_product_service_item_data($cart_item_data, $cart_item) {
$_product = new WC_Product( $cart_item['product_id'] );
$service_label = $_product->get_meta( '_custom_product_service_label' );
if (isset($cart_item['service_price'])) {
//$service_label = get_post_meta( $cart_item['product_id'], '_custom_product_service_label' );
$cart_item_data[] = array(
'name' => $service_label .__(" Service Fees", "woocommerce"),
'value' => strip_tags( '+ ' . wc_price( wc_get_price_to_display( $cart_item['data'], array('price' => $cart_item['service_price'] ) ) ) )
);
}elseif(!empty($service_label)){
$cart_item_data[] = array(
'name' => $service_label .__(" Service Not Included", "woocommerce"),
'value' => strip_tags( '+ ' . wc_price( wc_get_price_to_display( $cart_item['data'], array('price' => $cart_item['service_price'] ) ) ) )
);
}
return $cart_item_data;
}

Woocommerce emails template update and grab a custom field from order_details [duplicate]

On my WooCommerce based site, I recently added some code to display the shipping methods and prices for each order on the "Edit Order" page. Now, I would like to try and add those same fields to the "New Order" email template that gets sent to the admin. This is what I've got so far:
// Capture the available shipping methods, and costs:
function action_woocommerce_checkout_update_order_meta( $order_id ) {
// Get shipping packages
$packages = WC()->shipping()->get_packages();
// Set array
$rate_labels = array();
$rate_costs = array();
// Loop through packages
foreach ( $packages as $key => $package ) {
// Loop through package rates
foreach( $package['rates'] as $rate_id => $rate ) {
// Push to array
$rate_labels[] = $rate->get_label();
$rate_costs[] = $rate->get_cost();
}
}
// NOT empty
if ( ! empty ( $rate_labels ) ) {
// Update post meta
update_post_meta( $order_id, '_available_shipping_methods', $rate_labels );
update_post_meta( $order_id, '_available_shipping_method_cost', $rate_costs );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'action_woocommerce_checkout_update_order_meta', 10, 1 );
// Make it display on the edit order page:
function action_woocommerce_admin_order_data_after_shipping_address( $order ) {
// Get meta
$rate_labels = $order->get_meta( '_available_shipping_methods' );
$rate_costs = $order->get_meta( '_available_shipping_method_cost' );
$methods = array ( $rate_labels, $rate_costs );
// True
if ( $rate_labels ) {
// Loop
echo '<p><strong>Shipping Methods: </strong>';
foreach(array_combine($rate_labels, $rate_costs) as $rate_label => $rate_cost) {
echo '<p>' . $rate_label . ' - $' . $rate_cost . '</p>';
}
}
}
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'action_woocommerce_admin_order_data_after_shipping_address', 10, 1 );
Adding on to that, this is what I have been trying to get working, with no luck so far:
// Add it to the new order email template
add_filter( 'woocommerce_new_order', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $rate_labels, $sent_to_admin, $order ) {
$rate_labels = $order->get_meta( '_available_shipping_methods' );
$rate_costs = $order->get_meta( '_available_shipping_method_cost' );
$methods = array ( $rate_labels, $rate_costs );
if ( $rate_labels ) {
// Loop
echo '<p><strong>Shipping Methods: </strong>';
foreach(array_combine($rate_labels, $rate_costs) as $rate_label => $rate_cost) {
echo '<p>' . $rate_label . ' - $' . $rate_cost . '</p>';
}
}
}
Use instead the following for example:
add_action( 'woocommerce_email_after_order_table', 'wc_email_new_order_custom_meta_data', 10, 4);
function wc_email_new_order_custom_meta_data( $order, $sent_to_admin, $plain_text, $email ){
// On "new order" email notifications
if ( 'new_order' === $email->id ){
$rate_labels = $order->get_meta( '_available_shipping_methods' );
$rate_costs = $order->get_meta( '_available_shipping_method_cost' );
$methods = array ( $rate_labels, $rate_costs );
if ( $rate_labels ) {
// Loop
echo '<p><strong>Shipping Methods: </strong>';
foreach(array_combine($rate_labels, $rate_costs) as $rate_label => $rate_cost) {
echo '<p>' . $rate_label . ' - $' . $rate_cost . '</p>';
}
}
}
}
It should work.

WordPress Settings validation messages are shown twice

I'm adding a pretty basic (I feel) implementation of settings page validation for my WordPress plugin and it does work, but the error messages are shown twice. I stepped through my code and the calls to add_settings_error are only executed once.
<?php
class Example_plugin_Settings {
private $example_plugin_settings_options;
private $settings_options_name;
public function __construct() {
add_action( 'admin_menu', array( $this, 'example_plugin_settings_add_plugin_page' ) );
add_action( 'admin_init', array( $this, 'example_plugin_settings_page_init' ) );
$this->settings_options_name = 'example_plugin_options';
}
public function example_plugin_settings_add_plugin_page() {
add_options_page(
'Example-Plugin Connector Settings', // page_title
'Example-Plugin', // menu_title
'manage_options', // capability
'example-plugin-connector-settings', // menu_slug
array( $this, 'example_plugin_settings_create_admin_page' ) // function
);
}
public function example_plugin_settings_create_admin_page() {
$this->example_plugin_settings_options = get_option( 'example_plugin_options' ); ?>
<div class="wrap">
<h2>Example-Plugin Connector Settings</h2>
<p>Set up additional portals/currencies to be used with WooCommerce Currency Switcher (WOOCS). Enter a comma-delimited list of portals, then the corresponding comma-delimited list of currencies that those portals support.</p>
<?php settings_errors(); ?>
<form method="post" action="options.php">
<?php
settings_fields( 'example_plugin_settings_option_group' );
do_settings_sections( 'example-plugin-connector-settings-admin' );
submit_button();
?>
</form>
</div>
<?php }
public function example_plugin_settings_page_init() {
register_setting(
'example_plugin_settings_option_group', // option_group
$this->settings_options_name, // option_name
array( $this, 'example_plugin_settings_sanitize' ) // sanitize_callback
);
add_settings_section(
'example_plugin_settings_setting_section', // id
'Settings', // title
array( $this, 'example_plugin_settings_section_info' ), // callback
'example-plugin-connector-settings-admin' // page
);
add_settings_field(
'portals', // id
'Portals', // title
array( $this, 'portals_callback' ), // callback
'example-plugin-connector-settings-admin', // page
'example_plugin_settings_setting_section' // section
);
add_settings_field(
'currencies', // id
'Currencies', // title
array( $this, 'currencies_callback' ), // callback
'example-plugin-connector-settings-admin', // page
'example_plugin_settings_setting_section' // section
);
}
public function example_plugin_settings_sanitize($input) {
$sanitary_values = array();
if ( isset( $input['portals'] ) ) {
if ( '' == $input['portals'] ) {
$input['portals'] = '';
add_settings_error(
$this->settings_options_name,
'portals',
'Portals is a required field.',
'error'
);
} else {
$sanitary_values['portals'] = sanitize_text_field( trim( $input['portals'] ) );
}
}
if ( isset( $input['currencies'] ) ) {
if ( '' == $input['currencies'] ) {
$input['currencies'] = '';
add_settings_error(
$this->settings_options_name,
'currencies',
'Currencies is a required field.',
'error'
);
} else {
$sanitary_values['currencies'] = sanitize_text_field( trim( $input['currencies'] ) );
}
}
return $sanitary_values;
}
public function example_plugin_settings_section_info() {
}
public function portals_callback() {
printf(
'<input class="regular-text" type="text" name="example_plugin_options[portals]" id="portals" value="%s">',
isset( $this->example_plugin_settings_options['portals'] ) ? esc_attr( $this->example_plugin_settings_options['portals']) : ''
);
}
public function currencies_callback() {
printf(
'<input class="regular-text" type="text" name="example_plugin_options[currencies]" id="currencies" value="%s">',
isset( $this->example_plugin_settings_options['currencies'] ) ? esc_attr( $this->example_plugin_settings_options['currencies']) : ''
);
}
}
if ( is_admin() )
$example_plugin_settings = new Example_plugin_Settings();
It seems the problem is the line <?php settings_errors(); ?>. I got the base code from the WordPress Options Page Generator but maybe the code is outdated and that line is now redundant with newer versions of WordPress? I'm not sure.

Resources