Add custom field to the custom Woocommerce Emails - wordpress

I want to add delivery date in woocommerce emails, the hook I am using is
add_action( 'woocommerce_order_details_after_order_table', 'action_woocommerce_order_details_after_order_table', 10, 1 );
function action_woocommerce_order_details_after_order_table( $order ) {
...
$order_expected_delivery_date = get_post_meta($order_id, 'order_expected_delivery_date_'.$order_id, true);
if(!$order_expected_delivery_date) {
$delivery_date = getExpectedDeliveryDate($order);
update_post_meta($order_id, 'order_expected_delivery_date_'.$order_id, $delivery_date);
echo "<header><h2>Expected Delivery Date</h2></header><p style='font-size: 20px;'>".$delivery_date."<p>";
} else {
echo "<header><h2>Expected Delivery Date</h2></header><p style='font-size: 20px;'>".$order_expected_delivery_date."<p>";
}
}
but this hook is only called when the woocommerce order emails are triggered. I have made a custom email for sending to the warehouse as per requirement. This hook is not working for the custom emails.
I have tried to add the shortcode to the custom emails but that short code is also not working.
function delivery_date_shortcode( $atts, $content = null ) {
if( is_numeric($content) ) {
$order = wc_get_order( $content );
$order_data = $order->get_data();
return '<span class="caption">' . $order_data . '</span>';
}
}
add_shortcode( 'delivery', 'delivery_date_shortcode' );

I forgot to tell you that this issue is resolved.
// shortcode to display expected delivery date in warehouse email
function delivery_date_shortcode( $atts, $content = null ) {
$order = new \WC_Order($content);
$delivery_date = getExpectedDeliveryDate($order);
return "<header><h2 style='margin: 40px 0 18px;'>Expected Delivery Date</h2></header><p style='font-size: 20px;'>".$delivery_date."<p>";
}
add_shortcode( 'delivery', 'delivery_date_shortcode' );
The function getExpectedDeliveryDate($order) takes the order id and returns the expected delivery date.
Thank You.

Related

Redirecting customers to custom page after sale in WooCommerce

I'm trying to learn WooCommerce and WordPress plugins so I'm tweaking around. I'm trying to create a plugin that redirects customer to a custom page after checkout. The custom page/url can be defined when I create the product. Here is my code:
<?php
/*
Plugin Name: Custom Redirect After Sale
Description: Redirects customers to a custom page after a successful sale.
*/
// Register a new meta field for products
add_action( 'add_meta_boxes', 'custom_redirect_meta_box' );
function custom_redirect_meta_box() {
add_meta_box( 'custom_redirect_meta_box', 'Custom Redirect URL', 'custom_redirect_meta_box_callback', 'product', 'side' );
}
function custom_redirect_meta_box_callback( $post ) {
$value = get_post_meta( $post->ID, '_custom_redirect_url', true );
echo '<label for="custom_redirect_url">Custom Redirect URL:</label>';
echo '<input type="text" id="custom_redirect_url" name="custom_redirect_url" value="' . esc_attr( $value ) . '" style="width:100%">';
}
// Save the meta field value when the product is saved
add_action( 'save_post_product', 'save_custom_redirect_meta_box_data' );
function save_custom_redirect_meta_box_data( $post_id ) {
if ( isset( $_POST['custom_redirect_url'] ) ) {
update_post_meta( $post_id, '_custom_redirect_url', sanitize_text_field( $_POST['custom_redirect_url'] ) );
}
}
// Redirect to the custom page after a successful sale
add_action( 'woocommerce_payment_complete', 'custom_redirect_after_sale' );
function custom_redirect_after_sale( $order_id ) {
$order = wc_get_order( $order_id );
//$order->update_status( 'completed' );
$items = $order->get_items();
// Get the first product in the order
$product = reset($items);
// Get the custom redirect URL for the product
//$redirect_url = get_post_meta( $product->get_product_id(), '_custom_redirect_url', true );
$redirect_url = get_post_meta( $product->get_id(), '_custom_redirect_url', true );
//echo "Meta retrieved: " . $redirect_url;
//error_log("callback fired");
//echo "Payment complete ho ho ho";
if( $redirect_url ) {
wp_redirect( $redirect_url );
exit;
}
}
It seems the woocommerce_payment_complete hook is not firing. I tried to echo out the redirect url and text but it doesn't seem to work.
I'm on localhost and I'm using the cash on delivery payment method.
Basing this answer on the great https://rudrastyh.com/ - specifically this tutorial https://rudrastyh.com/woocommerce/thank-you-page.html#redirects this is the code that should work for what you are trying to do.
First, you hook into the template_redirect action to determine the URL where the customer needs to go
Getting the Order ID, you can get the products purchased for that order
Once you have the purchased products, you can get their ID and meta data, the redirect URL you saved for each. Note that while you use WP functions for handling meta, when working with WooCommerce it is best practice to use its CRUD methods. In case in the future they port products to custom tables, your code will continue working.
Implement the redirect with the WP function wp_safe_redirect
Note that what you are trying to achieve will have problems if customers purchase orders with more than 1 product, and you have more than 1 redirect URL. In this implementation, the first product in the order that has a saved redirect URL will override all others
add_action( 'template_redirect', 'purchased_product_redirect');
function purchased_product_redirect(){
if( !function_exists( 'is_wc_endpoint_url' )){
return;
}
// do nothing if we are not on the order received page
if( ! is_wc_endpoint_url( 'order-received' ) || empty( $_GET[ 'key' ] ) ) {
return;
}
// Get the order ID
$order_id = wc_get_order_id_by_order_key( $_GET[ 'key' ] );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get and Loop Over Order Items
foreach ( $order->get_items() as $item_id => $item ) {
$product_id = $item->get_product_id();
$product = wc_get_product($product_id);
if(!$product){
continue;
}
//Get the first product's redirect URL
$product_redirect_url = $product->get_meta('_custom_redirect_url');
if(!$product_redirect_url){
continue;
}
wp_safe_redirect( $product_redirect_url );
exit; // always exit after using wp_safe_redirect
}
}

I need create custom order tracking functionality in woo commerce

Hello I have a woo commerce website and I am selling some books every thing is cleared but I need create custom order tracking functionality in woo commerce code to add order tracking functionality for end user is it possible if possible how can I do this please help me.
I create a custom page name as woocommerce-custom-order-tracking.php
and code is given below
<?php
// Register a custom endpoint to handle order tracking
function wc_register_order_tracking_endpoint() {
add_rewrite_endpoint( 'order-tracking', EP_PAGES );
}
add_action( 'init', 'wc_register_order_tracking_endpoint' );
// Display the order tracking form
function wc_display_order_tracking_form() {
if ( ! is_wc_endpoint_url( 'order-tracking' ) ) {
return;
}
// Get the order id from the query string
$order_id = absint( $_GET['order_id'] );
// Get the order
$order = wc_get_order( $order_id );
if ( $order ) {
// Display the order tracking information
echo '<p>Order Number: ' . $order->get_order_number() . '</p>';
echo '<p>Order Status: ' . wc_get_order_status_name( $order->get_status() ) . '</p>';
echo '<p>Tracking Number: ' . get_post_meta( $order_id, '_tracking_number', true ) . '</p>';
} else {
echo '<p>Invalid order ID.</p>';
}
}
add_action( 'woocommerce_before_single_product', 'wc_display_order_tracking_form' );

Show the name of the chosen variation under the product title on the My Account > Downloads page

By default WooCommerce shows the attribute of a variable product in the title and I'm using this code to show the attribute below the title in the cart and checkout pages:
add_filter( 'woocommerce_product_variation_title_include_attributes', '__return_false' );
add_filter( 'woocommerce_is_attribute_in_product_name', '__return_false' );
But that doesn't work in My Account page, users see the full product name with no attribute.
To fix it I'm using the code below to show the attribute in the product title:
function show_attributes_outside_title_1( $enabled ) {
if ( !is_account_page() ) {
$enabled = false;
}
return $enabled;
}
add_filter( 'woocommerce_product_variation_title_include_attributes', 'show_attributes_outside_title_1' );
function show_attributes_outside_title_2( $enabled ) {
if ( !is_account_page() ) {
$enabled = false;
}
return $enabled;
}
add_filter( 'woocommerce_is_attribute_in_product_name', 'show_attributes_outside_title_2' );
But I'd like to show the attribute below the title (or a new column), it's easier to read and goes with the same desing you see in the cart and checkout pages.
There is some confusion in the initial part of the question.
You say you want to show the attribute under the product title on the cart and checkout page but then return __return_false, do you intend to do the opposite?
SOLUTION #1
You may want to reverse the check to make sure that your chosen product variation attribute is shown under the product name on your account page under Downloads (as evidenced by your comment above):
add_filter( 'woocommerce_product_variation_title_include_attributes', '__return_false' );
add_filter( 'woocommerce_is_attribute_in_product_name', '__return_false' );
add_filter( 'woocommerce_product_variation_title_include_attributes', 'show_attributes_outside_title_1' );
function show_attributes_outside_title_1( $enabled ) {
if ( is_account_page() ) {
$enabled = true;
}
return $enabled;
}
add_filter( 'woocommerce_is_attribute_in_product_name', 'show_attributes_outside_title_2' );
function show_attributes_outside_title_2( $enabled ) {
if ( ! is_account_page() ) {
$enabled = false;
}
return $enabled;
}
SOLUTION #2
If you want to leave the code in your question unchanged you can use the woocommerce_account_downloads_column_download-product hook where download-product is the id of the product name column (in the /my-account/downloads/ page). Here the documentation.
Finally, with the wc_get_formatted_variation function you can get the name of the chosen variation. For more information on parameters read the documentation.
// shows the variation chosen in the product name in the download table of the my-account page
add_action( 'woocommerce_account_downloads_column_download-product', 'change_product_download_name', 10, 1 );
function change_product_download_name( $download ) {
// gets the product object
$product = wc_get_product( $download['product_id'] );
// gets the name of the produc
$product_name = $download['product_name'];
// if the product is a variation
if ( $product->is_type( 'variation' ) ) {
// gets the name of the product with the chosen variation
$product_name = $product->get_name() . " - " . wc_get_formatted_variation( $product, true, false, false );
}
// print the product name (with or without product url)
if ( $download['product_url'] ) {
echo '' . esc_html( $product_name ) . '';
} else {
echo esc_html( $product_name );
}
}
The code has been tested and works. Add it to your active theme's functions.php.
I changed Vincenzo's answer a bit to make it look the same way I see the attributes in my Cart and Checkout pages. Here's the code in case anybody else needs it:
// Shows the variation chosen in the product name in the download table of the my-account page
add_action( 'woocommerce_account_downloads_column_download-product', 'change_product_download_name', 10, 1 );
function change_product_download_name( $download ) {
// gets the product object
$product = wc_get_product( $download['product_id'] );
// gets the name of the product
$product_name = $download['product_name'];
// define variable
$product_attributes = '';
// if the product is a variation
if ( $product->is_type( 'variation' ) ) {
// gets the name of the product with the chosen variation
$product_name = $product->get_name();
$product_attributes = wc_get_formatted_variation( $product, true, true, false );
}
// print the product name (with or without product url)
if ( $download['product_url'] ) {
echo '' . esc_html( $product_name ) . '<p>' . esc_html( $product_attributes ) . '</p>';
} else {
echo esc_html( $product_name ) . '<p>' . esc_html( $product_attributes ) . '</p>';
}
}
// Shows variation outside title in cart and checkout pages
add_filter( 'woocommerce_product_variation_title_include_attributes', '__return_false' );
add_filter( 'woocommerce_is_attribute_in_product_name', '__return_false' );
The last two filters replace my code and the first part solves the issue in the Downloads page.

How to add/update custom cart item data in the cart page

I want to add a comment to individual products in the cart page. I am new to woocommerce wordpress plugin so I have no idea how to do.
I have done some research. In that tutorial, I found that I can use woocommerce_add_cart_item_data hook this way:
add_filter( 'woocommerce_add_cart_item_data', 'add_comment', 10, 3 );
function add_comment( $cart_item_data, $product_id, $variation_id ) {
$cart_item_data['comment'] = 'This is comment';
return $cart_item_data;
}
but this does not work in my case.
I attach the Cart page image so you can understand.
I hope you guys understand what I want?
Thank you.
Below code will add a custom text to an item in cart:
You need to create a custom field "comment" for the product to use it here.
add_filter( 'woocommerce_add_cart_item_data', 'add_comment', 10, 3 );
function add_comment( $cart_item_data, $product_id, $variation_id ) {
$cart_item_data['comment'] = 'This is comment';
return $cart_item_data;
}
Add a Custom text/comment before Cart table in Cart Page:
add_action( 'woocommerce_before_cart_table', 'add_comment' );
function add_comment()
{
echo '<div class="woocommerce-info">This is comment</div>';
}
Add a Custom text/comment after Cart table in Cart Page:
add_action( 'woocommerce_after_cart_table', 'add_comment' );
function add_comment() {
echo '<div class="woocommerce-info">This is comment</div>';
}
HOW TO ADD AN INPUT FIELD TO WOOCOMMERCE CART ITEMS & Let users update input fields in the cart
https://pluginrepublic.com/how-to-add-an-input-field-to-woocommerce-cart-items/
Refer this link for a working solution to similar request:
https://stackoverflow.com/a/21818028/12291365
If you are okay with using the plugin, then this plugin will do the trick:
https://wordpress.org/plugins/wc-fields-factory/
Use code snippet below for adding custom values for each cart item.
Please add your logic for attaching values for each item
// Add custom value into cart item
add_filter('woocommerce_add_cart_item_data','sub_add_item_data',1,2);
if(!function_exists('sub_add_item_data'))
{
function sub_add_item_data($cart_item_data,$product_id)
{
// use condition for adding custom value here
$new_value = array(
'sub_custom_value' => 'custom value',
);
return array_merge($cart_item_data,$new_value);
}
}
// Extract custom values
add_filter('woocommerce_get_cart_item_from_session', 'sub_get_cart_items_from_session', 1, 3 );
if(!function_exists('sub_get_cart_items_from_session'))
{
function sub_get_cart_items_from_session($item,$values,$key)
{
if (array_key_exists( 'sub_custom_value', $values ) )
{
$item['sub_custom_value'] = $values['sub_custom_value'];
}
return $item;
}
}
// display in cart and checkout
add_filter('woocommerce_checkout_cart_item_quantity','sub_add_user_custom_option_from_session_into_cart',1,3);
add_filter('woocommerce_cart_item_price','sub_add_user_custom_option_from_session_into_cart',1,3);
if(!function_exists('sub_add_user_custom_option_from_session_into_cart'))
{
function sub_add_user_custom_option_from_session_into_cart($product_name, $values, $cart_item_key )
{
if(isset( $values['sub_custom_value'] ) && '' != $values['sub_custom_value'] )
{
$return_string = $product_name . "</a><dl class='variation'>";
$return_string .= "<table class='sub_options_table' id='" . $values['product_id'] . "'>";
$return_string .= "<tr><td>" . $values['sub_custom_value'] . "</td></tr>";
$return_string .= "</table></dl>";
return $return_string;
}
else
{
return $product_name;
}
}
}

How to save Meta Data in WordPress back-end with PHP

I am relatively new to Post Meta Data in the WordPress backend using PHP. I have written the code that creates the Meta Data. I need help saving the data for which I have written. It will also need to allow me to edit the data once saved.
In this case its for a text field.
I have created the Meta Data for the input field which displays well in the back-end WordPress admin area.
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
function cd_meta_box_add()
{
add_meta_box( 'my-meta-box-id', 'Job Title', 'cd_meta_box_cb', 'people', 'normal', 'high' );
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'cd_meta_box_add', 10, 2 );
}
function cd_meta_box_cb()
{
echo "<input type='text' name='jobtitle'>";
}
I just need assistance with the code that will save the above Meta Data to the DB and allow for editing and revisions
You were almost there.
The final part of the puzzle is the function that saves the metadata, but first we need to make a few adjustments to your existing code:
add_action( 'save_post', 'cd_meta_box_add', 10, 2 ); has to be moved outside cd_meta_box_add(), and
Change add_action( 'save_post', 'cd_meta_box_add', 10, 2 ); into add_action( 'save_post', 'cd_meta_box_add' ); as this action hook only receives one parameter (the post ID), and
You need to define the function that will process the data (and it can't be cd_meta_box_add as you have it now so we'll create a new one called save_cd_meta_box_data).
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'save_cd_meta_box_data' );
function save_cd_meta_box_data( $post_id ) {
// Autosaving, bail.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// #TODO
// You should add some additional security checks here
// eg. nonce, user capabilities, etc, to prevent
// malicious users from doing bad stuff.
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
if ( ! isset( $_POST['jobtitle'] ) ) {
return;
}
// Sanitize user input.
$my_data = sanitize_text_field( $_POST['jobtitle'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_job_title', $my_data );
}
Now that we're successfully saving the metadata into the database, let's allow the user to view it / edit it:
function cd_meta_box_cb( $post )
{
$job_title = get_post_meta( $post->ID, '_job_title', true );
echo "<input type='text' name='jobtitle' value='" . esc_attr( $job_title ) . "'>";
}
The final code should look like this:
/* Register and display metabox */
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
function cd_meta_box_add()
{
add_meta_box( 'my-meta-box-id', 'Job Title', 'cd_meta_box_cb', 'people', 'normal', 'high' );
}
function cd_meta_box_cb( $post )
{
$job_title = get_post_meta( $post->ID, '_job_title', true );
echo "<input type='text' name='jobtitle' value='" . esc_attr( $job_title ) . "'>";
}
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'save_cd_meta_box_data' );
function save_cd_meta_box_data( $post_id ) {
// Autosaving, bail.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// #TODO
// You should add some additional security checks here
// eg. nonce, user capabilities, etc, to prevent
// malicious users from doing bad stuff.
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
if ( ! isset( $_POST['jobtitle'] ) ) {
return;
}
// Sanitize user input.
$my_data = sanitize_text_field( $_POST['jobtitle'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_job_title', $my_data );
}

Resources