Display custom order item metadata only on WooCommerce admin orders - php

To display custom data , I use this hook 'woocommerce_checkout_create_order_line_item'. He works good. But it displays data in three places - in the admin panel (in order), in the order details and in the personal account. I need the data to be displayed only in the admin panel. how to do it?
My code
add_action( 'woocommerce_checkout_create_order_line_item', 'wdm_add_custom_order_line_item_meta', 10, 4 );
function wdm_add_custom_order_line_item_meta( $item, $cart_item_key, $values, $order )
{
if ( array_key_exists( 'file', $values ) ) {
$product_id = $item->get_product_id();
$permfile = $values['file'];
$basePath = plugin_base_url();
$fileid = $permfile;
....
$item->add_meta_data('File','<button > <a href="'.$fileid.'" download>' . Download. '</a></button>');
}
}

Use the following to display a custom download button on admin order items only (code is commented):
// Save custom order item meta
add_action( 'woocommerce_checkout_create_order_line_item', 'save_custom_order_item_meta', 10, 4 );
function save_custom_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( isset($values['file']) && ! empty($values['file']) ) {
// Save it in an array to hide meta data from admin order items
$item->add_meta_data('file', array( $values['file'] ) );
}
}
// Get custom order item meta and display a linked download button
add_action( 'woocommerce_after_order_itemmeta', 'display_admin_order_item_custom_button', 10, 3 );
function display_admin_order_item_custom_button( $item_id, $item, $product ){
// Only "line" items and backend order pages
if( ! ( is_admin() && $item->is_type('line_item') ) )
return;
$file_url = $item->get_meta('file'); // Get custom item meta data (array)
if( ! empty($file_url) ) {
// Display a custom download button using custom meta for the link
echo '<a href="' . reset($file_url) . '" class="button download" download>' . __("Download", "woocommerce") . '</a>';
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
The custom download button is only displayed in admin order items.

Related

Change order item custom meta data displayed label and value in WooCommerce Admin orders

In the Woocommerce admin screen, I'm attempting to use the order line meta data to display a button which will open up a new window with the URL of the dropship supplier. I have successfully pulled the supplier URL from the product on order and pushed it to the order line item.
I am able to change the meta data to a button but the consequence of that is the other custom fields which contain the custom options are wiped.
This is the full code which I have added to the functions.php file
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
// Get a product custom field value
$custom_field_value = get_post_meta( $item->get_product_id(), 'supplier_url', true );
// Update order item meta
if ( ! empty( $custom_field_value ) ){
$item->update_meta_data( '_supplier', $custom_field_value );
}
}
add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 20, 3 );
function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
// Change display_key
if( $meta->key === '_supplier' && is_admin() )
$display_key = __("Supplier", "woocommerce" );
return $display_key;
}
add_filter( 'woocommerce_order_item_display_meta_value', 'change_order_item_meta_value', 20, 3 );
function change_order_item_meta_value( $value, $meta, $item ) {
// Display supplier meta value as a button
if( $meta->key === '_supplier' && is_admin() ) {
$display_value = __('<a class="button" target="_blank" href="'.$value.'">Order</a>', 'woocommerce' );
return $display_value;
}
}
These images show the before and after of using the last block of code.
Before:
After:
Where have I gone wrong with my code and is what i'm trying to achieve possible?
The main mistake is on last function where $display_value should be replaced with just $value and then return $value; should be located at the end before last closing bracket.
I have also revisited all your code:
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
$supplier_url = $values['data']->get_meta( 'supplier_url' ); // Get product custom field value
// add product custom field as custom order item meta data
if ( ! empty($supplier_url) ){
$item->update_meta_data( '_supplier', $supplier_url );
}
}
add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 20, 3 );
function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
// Change displayed label for specific order item meta key
if( is_admin() && $item->get_type() === 'line_item' && $meta->key === '_supplier' ) {
$display_key = __("Supplier", "woocommerce" );
}
return $display_key;
}
add_filter( 'woocommerce_order_item_display_meta_value', 'change_order_item_meta_value', 20, 3 );
function change_order_item_meta_value( $value, $meta, $item ) {
// Change displayed value for specific order item meta key
if( is_admin() && $item->get_type() === 'line_item' && $meta->key === '_supplier' ) {
$value = __('<a class="button" target="_blank" href="'.$value.'">Order</a>', 'woocommerce' );
}
return $value;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Pass custom posted variable from a page to Woocommerce order data

I can add a custom variable to a WooCommerce order, using code like this - but only if the code is on the product page:
<form action="<?php echo esc_url( wc_get_checkout_url() ); ?>" method="post">
<?php
$value = isset( $_POST['dogname'] ) ? sanitize_text_field( $_POST['dogname'] ) : '';
echo '<div><label>Name of Dog</label><p><input name="dogname" value="' . $value . '"></p></div>';
?> <button type="submit">Checkout</button>
</form>
But how do I add the data to the order it if I am not on the product page? I redirect the page after add to cart to a custom page. On this custom page the cart is already populated with the product . But submitting this form on the custom page - goes to checkout but does not update or add the variable to the order. How would I update the order with my custom variable from my custom page?
Maybe I need some extra code for the button to update the order on click?
What code would I use for a button - that on click would post the form values to my order, and direct to another page?
Here below is a way to get posted data available in checkout page and anywhere else without loosing this posted data. For that we set the posted data to a WC session variable, so this posted data is available at any moment when needed.
The form on your page (example with multiple fields):
?><form action="<?php echo esc_url( wc_get_checkout_url() ); ?>" method="post">
<?php
$dogname = isset( $_POST['dogname'] ) ? sanitize_text_field( $_POST['dogname'] ) : '';
$dogcolor = isset( $_POST['dogcolor'] ) ? sanitize_text_field( $_POST['dogcolor'] ) : '';
?>
<div><label><?php _e("Name of Dog"); ?></label><p><input name="dogname" value="<?php echo $dogname; ?>"></p></div>
<div><label><?php _e("Color of Dog"); ?></label><p><input name="dogcolor" value="<?php echo $dogcolor; ?>"></p></div>
<button class="button" type="submit" name="dog_form" value="submited"><?php _e("Checkout"); ?></button>
</form><?php
The code that set the posted data to a WC_Session variable:
// Early enable customer WC_Session
add_action( 'init', 'wc_session_enabler' );
function wc_session_enabler() {
if ( is_user_logged_in() || is_admin() )
return;
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
}
// Set posted data in a WC session variable
add_action( 'template_redirect', 'set_custom_posted_data_to_wc_session' );
function set_custom_posted_data_to_wc_session() {
if ( is_checkout() && ! is_wc_endpoint_url() ) {
if ( isset($_POST['dog_form']) ) {
$values = array(); // Initializing
if ( isset($_POST['dogname']) && ! empty($_POST['dogname']) ) {
$values['dogname'] = sanitize_text_field($_POST['dogname']);
}
if ( isset($_POST['dogcolor']) && ! empty($_POST['dogcolor']) ) {
$values['dogcolor'] = sanitize_text_field($_POST['dogcolor']);
}
// Set data to a WC_Session variable
if ( ! empty($values) ) {
WC()->session->set('custom_data', $values);
}
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Then you can get that data on any function or template with:
$values = WC()->session->get('custom_data');
$dogname = isset($values['dogname']) ? $values['dogname'] : '';
$dogcolor = isset($values['dogcolor']) ? $values['dogcolor'] : '';
Save that data to order details:
// Save WC session data as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'action_checkout_add_custom_order_meta', 10, 2 );
function action_checkout_add_custom_order_meta( $order, $data ) {
$values = WC()->session->get('custom_data'); // Get data from WC Session variable
if( ! empty($values) ) {
if ( isset($values['dogname']) ) {
$order->update_meta_data( '_dogname', $values['dogname'] ); // Set dog name to order details
}
if ( isset($values['dogcolor']) ) {
$order->update_meta_data( '_dogcolor', $values['dogcolor'] ); // Set dog color to order details
}
// Remove the WC_Session variable (as we don't need it anymore)
WC()->session->__unset('custom_data');
}
}
Code goes in functions.php file of the active child theme (or active theme).
Then you can get that data from The WC_Order object order using:
$order = wc_get_order( $order_id ); // If needed, get the WC_Order object from order Id
$dogname = $order->get_meta('_dogname');
$dogcolor = $order->get_meta('_dogcolor');
Like in this hooked function that will display data on "Order received" page:
add_action( 'woocommerce_thankyou', 'thankyou_display_dog_data' );
function thankyou_display_dog_data( $order_id ) {
$order = wc_get_order( $order_id ); // Get an instance of the WC_Order object
$dog_name = $order->get_meta('_dogname');
$dog_color = $order->get_meta('_dogcolor');
echo ! empty($dog_name) ? '<p>' . $dog_name .'<p>' : '';
echo ! empty($dog_color) ? '<p>' . $dog_color .'<p>' : '';
}
Tested and works on last WooCommerce version.
To add some more functionality to LoicTheAztec answer using his thankyou_display_dog_data function. His included action shows the function on thank you after checkout form
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'thankyou_display_dog_data' ); //add to admin order data under shipping
add_action( 'woocommerce_admin_order_data_after_billing_address', 'thankyou_display_dog_data' ); //add to admin under billing - pick one or duplicate of shipping
add_action( 'woocommerce_order_details_after_order_table', 'thankyou_display_dog_data' ); //add to frontend customers my account
add_action( 'woocommerce_email_after_order_table', 'thankyou_display_dog_data', 15, 2 ); // add to emails

Add custom column product visibility to admin product list in Woocommerce 3

I am trying to add a custom column to admin product list with the Catalog Visibility value of the products (basically, I need to know easier which is Hidden and which is not).
My code so far for my child theme's functions.php:
add_filter( 'manage_edit-product_columns', 'custom_product_column', 10);
function custom_product_column($columns){
$columns['visibility'] = __( 'Visibility','woocommerce');
return $columns;
}
add_action( 'manage_product_posts_custom_column', 'custom_column_content', 10, 2 );
function custom_product_list_column_content( $column, $product_id ){
global $post;
$isitvisible = get_post_meta( $product_id, 'product_visibility', true );
switch ( $column ){
case 'visibility' :
echo $isitvisible;
break;
}
}
Can someone please guide me? The column is created (and the title displayed), but I get no data for the products.
There are some errors and mistakes in your code. Also since Woocommerce 3 product visibility is handled by Woocommerce custom taxonomy 'product_visibility'. Try the following instead:
// Add a new column to Admin products list with a custom order
add_filter( 'manage_edit-product_columns', 'visibility_product_column', 10);
function visibility_product_column($columns){
$new_columns = [];
foreach( $columns as $key => $column ){
$new_columns[$key] = $columns[$key];
if( $key == 'price' ) { // Or use: if( $key == 'featured' ) {
$new_columns['visibility'] = __( 'Visibility','woocommerce');
}
}
return $new_columns;
}
// Add content to new column raows in Admin products list
add_action( 'manage_product_posts_custom_column', 'visibility_product_column_content', 10, 2 );
function visibility_product_column_content( $column, $product_id ){
global $post;
if( $column =='visibility' ){
if( has_term( 'exclude-from-catalog', 'product_visibility', $product_id ) )
echo '<em style="color:grey;">' . __("No") . '</em>';
else
echo '<span style="color:green;">' . __("Yes") . '</span>';
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Woocommerce also allows you to hide products if they're out of stock. I needed to know which were excluded from catalog and which were hidden because they were out of stock. This small update to the code above uses an array to find all the hidden conditions I needed to know:
// Add content to new column rows in Admin products list
add_action( 'manage_product_posts_custom_column', 'visibility_product_column_content', 10, 2 );
function visibility_product_column_content( $column, $product_id ){
global $post;
if( $column =='visibility' ){
if( has_term( array('exclude-from-catalog', 'outofstock'),'product_visibility', $product_id ) )
echo '<em style="color:grey;">' . __("No") . '</em>';
else
echo '<span style="color:green;">' . __("Yes") . '</span>';
}
}

Disable the "bid" button from WooCommerce product pages for the author

I would like to Removal/disable/hide of "bid" button from product pages in WooCommerce for post authors of the post.
I am using WC vendors pro + Woocommerce + Wp Geine Auctions + WC Vendors Auction.
Please find the link of the screen shot below:
The Live Link to the product
How can I do it please?
As this buttons are already customized by you or some plugins, I am not sure at 100% that it will work for you, even if it works on my test server.
The first function is a conditional function that detects for a product if the current user is the author (the vendor) of this product.
Then on shop and archives pages the add to cart button is replace by a custom button liked to the product.
To finish on single product page the button is replace by a fake button with a custom text (here "Not Allowed")…
Here is the code:
// Custom conditional function (detecting the vendor of a product)
if( ! function_exists( 'is_the_vendor' ) ){
function is_the_vendor( $product ){
$current_user_id = get_current_user_id();
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
// Get the product post object to get the post author
$post_obj = get_post( $product_id );
$post_author = $post_obj->post_author;
if( $post_author == $current_user_id ) return true;
else return false;
}
}
// Shop and archives pages: we replace the button add to cart by a link to the product
add_filter( 'woocommerce_loop_add_to_cart_link', 'custom_text_replace_button', 10, 2 );
function custom_text_replace_button( $button, $product ) {
if( is_the_vendor( $product ) ){
$button_text = __("View product", "woocommerce");
return '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
} else {
return $button;
}
}
// replacing add to cart button and quantities by a custom inactive button
add_action( 'woocommerce_single_product_summary', 'replacing_template_single_add_to_cart', 1, 0 );
function replacing_template_single_add_to_cart() {
global $product;
if( is_the_vendor( $product ) ):
// Removing add to cart button and quantities
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
// The text replacement
add_action( 'woocommerce_single_product_summary', function(){
// set below your custom text
$text = __('Not allowed', 'woocommerce');
// Temporary style CSS
$style_css = 'style="border: solid 1px red; padding: 0 6px; text-align: center;"';
// Output your custom text
echo '<a class="button custom-button" style="background-color: grey !important;">'.$text.'</a>';
}, 30 );
endif;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works. you will get this:
And this:

WooCommerce Checkout url hook - Change condition based on product category

Wondering if anyone could help me to customize this code. I would like to change the applied condition in this code:
add_filter( 'woocommerce_get_checkout_url', 'change_checkout_url', 30 );
function change_checkout_url( $url ) {
$allowed_countries = array('NO');
$customer_country = WC()->customer->get_default_country();
if( !in_array( $customer_country , $allowed_countries ) ) {
$url = wc_get_page_permalink( 'checkout' );
}
return $url;
}
Is it possible instead, for products that belongs to some category in WooCommerce, to have a custom checkout url?
2020 Update: Only for WooCommerce 3+
Yes it's possible, making some changes:
add_filter( 'woocommerce_get_checkout_url', 'custom_checkout_url', 30 );
function custom_checkout_url( $checkout_url ) {
// Define your product categories (term Id, slug or name)
$categories = array('Cat name1', 'Cat name2');
$custom_url = 'http://my_custom_url.com/checkout/'; // <= custom URL
$cart_items = WC()->cart->get_cart();
if ( sizeof($cart_items) > 0 ) {
foreach ( $cart_items as $cart_item ) {
if( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ){
return $custom_url;
}
}
}
return $checkout_url;
}
This code goes in your plugin file or on function.php file of your active child theme or theme
References:
Display WooCommerce checkout link
Using has_term( $category, 'product_cat') for WC products category condition
Get Cart products id on checkout WooCommerce page, to display product images

Categories