I'm trying to hook a function to the order deletion (when permanently delete is clicked from admin page) but for some reason the function isn't called. My code looks something like
add_action('woocommerce_before_delete_order_item', function($id) {
$order = new WC_Order($id);
//do some stuff with order meta data
}, 10, 1);
I tried to throw and exception inside the function but no error occurred. Can somebody help?
The woocommerce_before_delete_order_item action runs every time an item is deleted from an order, not every time an order is deleted. You need to use the before_delete_post hook:
add_action('before_delete_post', function($id) {
$post_type = get_post_type($id);
if ($post_type !== 'shop_order') {
return;
}
$order = new WC_Order($id);
//do some stuff with order meta data
}, 10, 1);
Depending on what it is you want to do, you may want to hook on to the action at an earlier stage by changing the priority argument from 10 to something smaller.
if you intend to use the Move to thrash from the order details page on admin dashboard, you can use the wp_trash_post. The before_delete_post didn't work for me.
function onOrderDelete($orderId){
$post_type = get_post_type($orderId);
if($post_type !== 'shop_order') {
return;
}
$order = wc_get_order($orderId);
// do whatever with $order
}
add_action('wp_trash_post', 'onOrderDelete', 10, 1);
function restrict_post_deletion($post_ID){
$type = get_post_type($post_ID);
if($type == 'shop_order'){
$order = new WC_Order($post_ID);
//do some stuff with order data
}
}
add_action('wp_trash_post', 'restrict_post_deletion', 10, 1);
add_action('before_delete_post', 'restrict_post_deletion', 10, 1);
Try this code snippet
Related
I add a custom function in an add_action hook which do something. how can I make my custom function do it's process independently? i.e. the action hook just activate my custom function and end the add_action.
add_action('woocommerce_order_status_changed', 'update_inventory',11, 1);
function update_inventory($order_id){
$order = wc_get_order( $order_id );
$given_data = array(...);
$given_url = 'https://...'
if ($order->status == 'processing') {
$switch = true;
$given_data;
$given_url;
do_sth_outsite($switch, $given_data, $given_url);
}
}
My custome function is do_sth_outsite
i'm having a odd issue with WooCommerce.
I have a plugin I developed that sends data from WooCommerce orders to HubSpot. The plugin needs to fire whenever a new order is placed OR an existing order is updated . I've been using the following truncated code to try to achieve this:
add_action('save_post', 'printout', 10, 3);
function printout($post_ID, $post, $update)
{
if ("shop_order" == $post->post_type) {
$msg = $post_ID;
delegator($msg);
}
}
function delegator($order_id){
$order = get_woocommerce_order($order_id);
// assigns the actual data of the order to the $data variable
$data = get_woocommerce_order_data($order);
// assign User e-mail for search
$email = $order->get_billing_email();
//$email = get_post_meta( $order_id, '_billing_email', true );
}
The problem i'm having is that upon new Orders being made, WordPress can't get the order details, specifically a e-mail (it returns null). The hook does return an order number, so I don't think it's the hook doing this but something else.
The odd part is if after the order is placed and I go into the Order page and just hit update on the order, it works!
So I'm wondering what I'm missing / what's wrong here. Does the flow of the hook fire before WooCommerce can make database calls?
Thanks for any help. Been driving me mad!
For orders added/updated through admin, use the code below
add_action('save_post_shop_order', 'backend_delegator', 10, 3);
function backend_delegator($post_id, $post, $update) {
// Orders in backend only
if (!is_admin())
return;
// Get an instance of the WC_Order
$order = new WC_Order($post_id);
//Fired when create a new order
if (!$update) {
$email = $order->get_billing_email();
}
if ($update) {
$email = $order->get_billing_email();
}
}
For orders placed from checkout, use the code below.
add_action('woocommerce_new_order', 'frondend_delegator', 10, 2);
function frondend_delegator($order_id, $order) {
$email = $order->get_billing_email();
}
I found many questions like this but nothing matching to my requirement.Here my requirement is to lock a specific page named settings. It's not to be deleted by others.But it should be able to edit. Is there any way to lock a specific page using its page id or name.
Create a hook in themes function file as per below:
function restrict_page_deletion($post_ID){
$user = get_current_user_id();
$restricted_pageId = 4;
if($post_ID == $restricted_pageId)
{
echo "You are not authorized to delete this page.";
exit;
}
}
add_action('before_delete_post', 'restrict_page_deletion', 10, 1);
Pass your page id to a restricted_pageId variable.
If you want to implement this functionality for multiple pages then use the array in place of the variable.
Admin can move a page to trash but admin will not able to delete it.
If you want to block admin for trach functionality then call a hook on "wp_trash_post" action.
add_action('wp_trash_post', 'restrict_page_deletion', 10, 1);
function wpse_312694_restrict_page_deletion( $caps, $cap, $user_id, $args ) {
$post_id = $args[0];
if ( $cap === 'delete_post' && $post_id === 117 ) {
$caps[] = 'do_not_allow';
}
return $caps;
}
add_filter( 'map_meta_cap', 'wpse_312694_restrict_page_deletion', 10, 4 );
I have attached a function to the woocommerce_checkout_order_processed hook:
//check if woocommerce is acive
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
add_action('woocommerce_checkout_order_processed', 'wc_on_place_order');
}
The wc_on_place_order function is to be executed after the user clicks on the PLACE ORDER button. However, it's so odd that the function is executed twice.
My wc_on_place_order function calls an external api written in C#:
function wc_on_place_order( $order_id ) {
global $wpdb;
// get order object and order details
$order = new WC_Order( $order_id );
// get product details
$items = $order->get_items();
//return $items;
$products = array();
foreach ($items as $item) {
array_push($products,
array('userid' => $order->user_id, 'descr' => $item['name'], 'amt' => (float)$item['line_total'])
);
}
//passing $products to external api using `curl_exec`
. . . .
//on successful call, the page should be showing an `alert`, however, it does not
// the handle response
if (strpos($response,'ERROR') !== false) {
print_r($response);
} else {
echo "<script type='text/javascript'>alert($response)</script>";
}
}
After debugging on C# API, I noticed that it the service is being called twice, thus, the checkout is being saved twice to the API database.
Is there something wrong with the wc_on_place_order function or is woocommerce_checkout_order_processed called twice when clicking the PLACE ORDER?
Interestingly, adding return $items after $items = $order->get_items() somehow, the C# api was only called once:
// get product details
$items = $order->get_items();
return $items; //this line
Why is that so?
One more question I would like to ask, is woocommerce_checkout_order_processed the right hook I should use? I have been searching the web for the correct hook to use and it seems that woocommerce_checkout_order_processed is used in the most post. I can't use the woocommerce_thankyou hook as it is also calling the API if I refresh the page.
Any idea will be really appreciated.
EDIT:
I used woocommerce_after_checkout_validation hook which fires after pre-validations on checkout. I can't remember though why woocommerce_checkout_order_processed is being fired twice but I just changed some kind of settings in WooCommerce options page. I can't remember which.
Useful Links from the Comments:
Visual Representation of the WooCommerce hooks
WordPress Action References
I always use the hook woocommerce_payment_complete This will fire as the name suggests after the order has been paid.
function order_payment_complete( $order_id ){
$order = wc_get_order( $order_id );
/* Insert your code */
}
add_action( 'woocommerce_payment_complete', 'order_payment_complete' );
Thanks for any help with this.
I need to know how to hook wp_insert_post (or whatever is similar and better?) without it firing multiple times. What is the correct way to do this in WordPress?
For example:
In Plugin.php
add_filter( 'wp_insert_post', 'add_data') );
...
function add_data()
{
// This line is outputted twice
terseErrorLog("This code was executed.");
}
Try this:
function add_data() {
global $post;
if ($post - > post_status == "publish") {
terseErrorLog("This code was executed.");
}
}
add_action('save_post', 'add_data');