Custom action button in WooCommerce admin orders that send an email - php

I added a action button in the order page, the problem is no passing any data to the function.
add_filter( 'woocommerce_admin_order_actions', 'add_customer_second_payment_reminder_button', 100, 2 );
function add_customer_second_payment_reminder_button( $actions, $order ) {
if ( $order->has_status(array( 'partially-paid' ) )) {
$actions['email_reminder'] = array(
'url' => wp_nonce_url( admin_url('admin-ajax.php?action=customer_second_payment_reminder_button&order_id=' . $order->get_id() )),
'name' => __( 'Email Second Payment Reminder' , 'woocommerce-deposits' ),
'action' => 'email_reminder',
);
}
return $actions;
}
add_action( 'wp_ajax_customer_second_payment_reminder_button', 'customer_second_payment_reminder_button' );
function customer_second_payment_reminder_button( $order_id ) {
do_action( 'woocommerce_deposits_second_payment_reminder_email' , $order_id );
}
add_action( 'admin_head', 'add_customer_second_payment_reminder_button_css' );
function add_customer_second_payment_reminder_button_css() {
echo '<style>.wc-action-button-'.'email_reminder'.'::after { font-family: woocommerce !important; content: "\e030" !important; }</style>';
}
so always show a 0 when i use the button.
customer_second_payment_reminder_button function don't receive the ?order_id parameter from the url.
i put a var_dump($order_id); in the function and show string(0) "" 0
how i can pass the order id to the function?

There are some mistakes and some missing things in your code:
There are no function arguments with wp_ajax_{action} or wp_ajax_nopriv_{action} action hooks.
The order ID is sent via the URL, so you can catch it through $_GET variable
You have to secure your Ajax function and to embed a redirection at the end. If not you get a white page. Also never forget exit; at the end...
So your functional code will be:
add_filter( 'woocommerce_admin_order_actions', 'add_customer_second_payment_reminder_button', 100, 2 );
function add_customer_second_payment_reminder_button( $actions, $order ) {
if ( $order->has_status( array('partially-paid') ) ) {
$actions['email_reminder'] = array(
'url' => wp_nonce_url(
admin_url('admin-ajax.php?action=customer_second_payment_reminder&order_id=' . $order->get_id() ),
'customer-second-payment-reminder'
),
'name' => __( 'Email Second Payment Reminder', 'woocommerce-deposits' ),
'action' => 'email_reminder',
);
}
return $actions;
}
add_action( 'wp_ajax_customer_second_payment_reminder', 'get_customer_second_payment_reminder' );
function get_customer_second_payment_reminder() {
if ( current_user_can('edit_shop_orders') && check_admin_referer('customer-second-payment-reminder') &&
isset($_GET['order_id']) && get_post_type( absint( wp_unslash($_GET['order_id']) ) ) === 'shop_order' ) {
$order_id = absint( wp_unslash($_GET['order_id']) );
$order = wc_get_order($order_id);
if( is_a($order, 'WC_Order') ) {
do_action( 'woocommerce_deposits_second_payment_reminder_email', $order_id, $order );
update_post_meta( $order_id, '_reminder_button', 'OK' ); // For testing purpose (to be removed)
}
}
wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'edit.php?post_type=shop_order' ) );
exit;
}
add_action( 'admin_head', 'customer_second_payment_reminder_button_css' );
function customer_second_payment_reminder_button_css() {
global $pagenow;
if( $pagenow === 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] === 'shop_order' ) {
echo '<style>.wc-action-button-'.'email_reminder'.'::after { font-family: woocommerce !important; content: "\e02d" !important; }</style>';
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related

Hiding custom product tabs if there is content doesn't work

I use code that displays custom WooCommerce product tabs. This code is based on "Custom metabox content displayed in single product additional tabs on Woocommerce"
// Add a custom metabox
add_action( 'add_meta_boxes', 'additional_product_tabs_metabox' );
function additional_product_tabs_metabox()
{
add_meta_box(
'add_product_metabox_additional_tabs',
__( 'Specifications Product Tabs', 'woocommerce' ),
'additional_product_tabs_metabox_content',
'product',
'normal'
);
}
// Add custom metabox content
function additional_product_tabs_metabox_content( $post )
{
// Technical Specification
echo '<h4>' . __( 'Technical Specification', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_technical_specification', true );
wp_editor( $value, '_technical_specification', array( 'editor_height' => 150 ) );
// Nonce field (for security)
echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}
// Save product data
add_action( 'save_post_product', 'save_additional_product_tabs', 10, 1 );
function save_additional_product_tabs( $post_id ) {
// Security check
if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ! current_user_can( 'edit_product', $post_id ) ) {
return $post_id;
}
// Sanitize user input and save the post meta fields values.
if( isset($_POST[ '_technical_specification' ]) )
update_post_meta( $post_id, '_technical_specification', wp_kses_post($_POST[ '_technical_specification' ]) );
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
global $product;
// Technical Specification Tab
if ( ! empty($product) ) {
$tabs['technical_specification_tab'] = array(
'title' => __( 'Technical Specification', 'woocommerce' ),
'priority' => 60,
'callback' => 'woo_technical_specification_tab_content'
);
}
return $tabs;
}
function woo_technical_specification_tab_content() {
global $product;
echo'<p class="specification-text">'. $product->get_meta( '_technical_specification' ) . '</p>';
}
add_action('wp_footer', 'woo_activate_pdf_script');
function woo_activate_pdf_script(){
?>
<script>
var i, links = document.getElementsByTagName('a');
for(i=0; i<links.length; i++) {
if (links[i].href.match(/.pdf/ig)) links[i].className = 'pdf-icon';
}
</script>
<?php
}
Can you also check this code to see if it is correct? Tab visibility doesn't work here if there's no content in it.
And the speed of saving the product page when editing has increased.
I would be glad to have your help!
Try This
There is most likely a better way of doing this, but I've achieved this in the past with the following
if( get_field('directions') )
{
echo the_field('directions');
}
else
{
echo "<style>.direction_tab_tab { display:none !important; }</style>";
}

How can i change status button

I'm trying to make a button that changes my order status, but it can only appear on the view-quote page when the order status is at: ywraq-pending
I'm trying this code, but it shows up in all statuses:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification
if( is_wc_endpoint_url( 'view-quote' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;">
<a class="button" href="'.$data['url'].'">'.$data['name'].'</a>
</div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}
Can anybody help me?
If I understood your question clearly, you missed checking order status in the complete_action_button_my_accout_order_view function, so, you can achieve that with this code:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification && only for orders with ywraq-pending status
if( is_wc_endpoint_url( 'view-quote' )
&& $order->has_status( 'ywraq-pending' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;"><a class="button" href="'.$data['url'].'">'.$data['name'].'</a></div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}

Add a checkbox as Woocommerce admin product option that hides related products

To make this as simple and as easy as possible, I'm trying to add this checkbox on the top row next to the product type selector where you would normally find Virtual and Download.
The idea is to have the checkbox there so that no matter the product type, it is always available.
This is what I've tried:
add_action( 'woocommerce_product_type_options', 'remove_related_products_checkbox' );
function remove_related_products_checkbox() {
woocommerce_wp_checkbox( array(
'id' => '_remove_related_products',
'class' => '',
'label' => 'Remove Related Products?'
) );
}
add_action( 'save_post_product', 'related_products_checkbox_save' );
function remove_related_products_checkbox_save( $product_id ) {
global $pagenow, $typenow;
if ( 'post.php' !== $pagenow || 'product' !== $typenow ) return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( isset( $_POST['_remove_related_products'] ) ) {
update_post_meta( $product_id, '_remove_related_products', $_POST['_remove_related_products'] );
} else
delete_post_meta( $product_id, '_remove_related_products' );
}
add_action( 'woocommerce_after_single_product_summary', 'remove_related_products_checkbox_display', 1 );
function remove_related_products_checkbox_display() {
global $product;
if ( ! empty ( get_post_meta( $product->get_id(), '_remove_related_products', true ) ) ) {
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );
}
}
But it doesn't work… Any advice please?
Your code is a bit outdated since WooCommerce 3 and there are some mistakes.
Try the following instead:
add_filter( 'product_type_options', 'hide_related_products_option' );
function hide_related_products_option( $fields ) {
$fields['hide_related'] = array(
'id' => '_hide_related',
'wrapper_class' => '',
'label' => __('Remove Related Products'),
'description' => __( 'Remove/Hide related products.', 'woocommerce' ),
'default' => 'no'
);
return $fields;
}
add_action( 'woocommerce_admin_process_product_object', 'hide_related_products_option_save' );
function hide_related_products_option_save( $product ) {
$product->update_meta_data( '_hide_related', isset( $_POST['_hide_related'] ) ? 'yes' : 'no' );
}
add_action( 'woocommerce_after_single_product_summary', 'remove_related_products_checkbox_display', 1 );
function remove_related_products_checkbox_display() {
global $product;
if ( $product->get_meta('_hide_related') === 'yes' ) {
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Related: Add checkbox to product type option in Woocommerce backend product edit pages
In order to hide the Related Products section you can display a checkbox to disable related products. You just need to add the following snippet to your functions.php.
add_action( 'woocommerce_product_options_general_product_data', 'codeithub_add_related_checkbox_products' );
function codeithub_add_related_checkbox_products() {
woocommerce_wp_checkbox( array(
'id' => 'hide_related',
'class' => '',
'label' => 'Hide Related Products'
)
);
}
add_action( 'save_post_product', 'codeithub_save_related_checkbox_products' );
function codeithub_save_related_checkbox_products( $product_id ) {
global $pagenow, $typenow;
if ( 'post.php' !== $pagenow || 'product' !== $typenow ) return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( isset( $_POST['hide_related'] ) ) {
update_post_meta( $product_id, 'hide_related', $_POST['hide_related'] );
} else delete_post_meta( $product_id, 'hide_related' );
}
add_action( 'woocommerce_after_single_product_summary', 'codeithub_hide_related_checkbox_products', 1 );
function codeithub_hide_related_checkbox_products() {
global $product;
if ( ! empty ( get_post_meta( $product->get_id(), 'hide_related', true ) ) ) {
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );
}
}

Editing Custom product tab content in Woocommerce Admin product pages

In WooCommerce, I would like to add custom global product tab just like additional info when a new product is created.
I am able to create new tab but cannot update anything on create new product page.
I can see it on display page but how to add info through product edit page. I know I can use custom fields but I am looking to have it on product page to allow shop manager or others to fill this additional shipping tab.
My Code is
add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
function woo_new_product_tab( $tabs ) {
// Adds the new tab
$tabs['test_tab'] = array(
'title' => __( 'Shipping', 'woocommerce' ),
'priority' => 50,
'callback' => 'woo_new_product_tab_content'
);
return $tabs;
}
function woo_new_product_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<p>'.get_post_meta($prod_id,'Shipping',true).'</p>';
}
You can add a custom Metabox in Admin Product pages that will allow Shop Managers to add content for your custom product tab. You will get this:
Here is the code:
// Adding a custom Meta container to admin products pages
add_action( 'add_meta_boxes', 'create_custom_meta_box' );
if ( ! function_exists( 'create_custom_meta_box' ) )
{
function create_custom_meta_box()
{
add_meta_box(
'custom_product_shipping_field',
__( 'Custom Shipping Tab information', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
}
}
// Custom metabox content in admin product pages
if ( ! function_exists( 'add_custom_content_meta_box' ) )
{
function add_custom_content_meta_box( $post )
{
$value = get_post_meta( $post->ID, '_shipping_tab', true ) ? get_post_meta( $post->ID, '_shipping_tab', true ) : '';
wp_editor( $value, 'custom_shipping_tab', array( 'editor_height' => 100 ) );
echo '<input type="hidden" name="custom_product_field_nonce" value="' . wp_create_nonce() . '">';
}
}
//Save the data of the Meta field
add_action( 'save_post', 'save_custom_content_meta_box', 10, 1 );
if ( ! function_exists( 'save_custom_content_meta_box' ) )
{
function save_custom_content_meta_box( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'custom_product_field_nonce' ] ) ) {
return $post_id;
}
$nonce = $_REQUEST[ 'custom_product_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
update_post_meta( $post_id, '_shipping_tab', wp_kses_post($_POST[ 'custom_shipping_tab' ]) );
}
}
Then your own code will be:
// Add product custom "Shipping" tab
add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
function woo_new_product_tab( $tabs ) {
$tabs['test_tab'] = array(
'title' => __( 'Shipping', 'woocommerce' ),
'priority' => 50,
'callback' => 'shipping_product_tab_content'
);
return $tabs;
}
// The Shipping tab content
function shipping_product_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), '_shipping_tab' ,true ).'</p></div>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.

WordPress Redirect Trouble

I'm hoping someone could explain a way to use a variable within the wp_redirect() function? Thanks in advance.
There are two variables:
wp_redirect( $location, $status );
$location is the absolute URI which the user will be redirected to.
$status is the status code to use (eg, 301). Default is 302 (so you can leave it blank if you want).
Your code is not storing value of url and even not getting in add_to_cart_redirect function.Try below code
//* Add/Display Fields
add_action( 'woocommerce_product_options_general_product_data', 'rv_woo_add_custom_general_fields' );
function rv_woo_add_custom_general_fields() {
global $post_id;
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => '_rv_woo_product_custom_redirect_url',
'label' => __( 'Redirect on Add to Cart', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter a URL to redirect the user to after this product is added to the cart.', 'woocommerce' ) ,
'value' => get_post_meta($post_id,'c',true)
)
);
echo '</div>';
}
//* Save Fields
add_action( 'woocommerce_process_product_meta', 'rv_woo_add_custom_general_fields_save' );
function rv_woo_add_custom_general_fields_save( $post_id ){
$rv_woo_redirect_url = get_post_meta($post_id,'c',true);
if( !empty( $rv_woo_redirect_url ) ) {
update_post_meta( $post_id, 'c', esc_url( $rv_woo_redirect_url ) );
}
}
add_filter('add_to_cart_redirect', 'redirect_elsewhere');
function redirect_elsewhere() {
global $woocommerce, $post;
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
$rv_woo_redirect_url = get_post_meta($product_id,'c',true);
if( !empty( $rv_woo_redirect_url ) ) {
wp_redirect( $rv_woo_redirect_url );
exit;
}
}

Categories