I'm working on a Woocommerce site that is using the following plugin: https://docs.woothemes.com/document/woocommerce-order-delivery/ ("WooCommerce Order Delivery")
The plugin is now displayed on the Checkout page under the billing fields in the checkout_shipping section, I am trying to change this location to the checkout_order_review section by hooking in to the functions.
But I can't seem to get it working.
My code in my functions.php:
function action_woocommerce_checkout_shipping( $instance ) {
global $woocommerce;
if ( is_checkout() && $woocommerce->cart->needs_shipping() ) {
echo 'Hi World!';
if ( wc_od() ){
echo 'Found wc_od function';
}
remove_action( 'woocommerce_checkout_shipping', 'checkout_content' );
}
};
// add the action
add_action( 'woocommerce_checkout_shipping', 'action_woocommerce_checkout_shipping' );
My thought behind this code was that I remove the function 'checkout_content' which retrieves the plugin template and then add the action to the woocommerce_checkout_order_review function to display it in the order review section.
But my remove_action doesn't seem to work.
The code in the plugin that adds the checkout_content action:
protected function __construct() {
// WP Hooks.
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
// WooCommerce hooks.
add_action( 'woocommerce_checkout_shipping', array( $this, 'checkout_content' ), 99 );
add_action( 'woocommerce_checkout_process', array( $this, 'validate_delivery_date' ) );
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_order_meta' ) );
// Delivery date validation hooks.
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_delivery_day' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_minimum_days' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_maximum_days' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_no_events' ), 10, 2 );
}
Can someone maybe give me a push in the right direction?
Am I doing this wrong ? or is there a better way of achieving this?
You have two issues.
Firstly you need to specify the execution priority when you remove action, or at least you do when it is anything other than the default, 10. In your case the execution priority is 99.
Secondly, checkout_content() is a class function, not a standalone function so you need to specify this in the function reference.
So your remove_action line of code will be:
remove_action( 'woocommerce_checkout_shipping', array( $the_class_variable, 'checkout_content' ), 99 );
where $the_class_variable is the instance of the class containing that __construct() function. How you refer to this depends on how the class has been instantiated in the plugin.
You can read about different ways of instantiating a class and the corresponding remove_action at http://jespervanengelen.com/different-ways-of-instantiating-wordpress-plugins/
You can read about remove_action this in https://codex.wordpress.org/Function_Reference/remove_action
Related
I am trying to allow the usage of decimal quantities in the admin panel.
I had added the following code:
remove_filter( 'woocommerce_stock_amount', 'intval' );
add_filter( 'woocommerce_stock_amount', 'floatval' );
But when I edit the order and try to change the quantity to decimals, after hitting update order, nothing happens and the following error comes in the console:
An invalid form control with name='order_item_qty[328]' is not focusable.
(328 is the item I Tried to edit)
Any solutions for this?
Ok I found the answer after digging in some Woocommerce Core Files:
Instead of using this:
add_filter( 'woocommerce_quantity_input_step', array( &$this, 'min_decimal' ), 99 );
I used this:
if(is_admin()){
add_filter( 'woocommerce_quantity_input_step', array( &$this, 'admin_qty_step' ), 99 );
}
else{
add_filter( 'woocommerce_quantity_input_step', array( &$this, 'min_decimal' ), 99 );
}
While the min_decimal method returns a string with a preset quantity step on the front-end and admin_qty_step returns "0.1" on the Back-end Interfaces.
Hope someone find this helpful
I am using Wordpress 4.6 with WooCommerce 2.6.4 and Smart Coupon 3.1.2 plugin.
I would like to move the "available coupons" section from the top of my checkout page to the bottom.
In the plugin file I've detected this structure and the action that I need to change.
I need to change it to 'woocommerce_after_checkout_form' but I can't get my head around on how to override it from the functions.php file.
I've already tried directly from the plugin to change it and it works like I would but we all know that it's a wrong approach to edit a plugin's behaviour.
Any help and documentation would be really helpful.
class WC_Smart_Coupons {
...
public function __construct() {
...
add_action( 'woocommerce_before_checkout_form', array( $this, 'show_available_coupons_before_checkout_form' ), 11 );
...
}
}
...
function initialize_smart_coupons() {
$GLOBALS['woocommerce_smart_coupon'] = new WC_Smart_Coupons();
}
add_action( 'plugins_loaded', 'initialize_smart_coupons' );
So, I had similar problem today. You can do following to move that section to different place.
To remove:
remove_action( 'woocommerce_before_checkout_form', array( $GLOBALS['woocommerce_smart_coupon'], 'show_available_coupons_before_checkout_form' ), 11 );
To add:
add_action( 'any_action', array( $GLOBALS['woocommerce_smart_coupon'], 'show_available_coupons_before_checkout_form' ), 11 );
The accepted solution doesn't work for the Smart Coupons version I use (4.12.2).
To change the "available coupons" position use the following instead:
$obj_inst = WC_SC_Display_Coupons::get_instance();
remove_action( 'woocommerce_before_checkout_form', array( $obj_inst, 'show_available_coupons_before_checkout_form' ), 11 );
add_action( 'woocommerce_checkout_after_customer_details', array( $obj_inst, 'show_available_coupons_before_checkout_form' ), 11 );
A nifty visual list of woocommerce checkout page hooks can be found here.
I want to write a custom plugin that does some action after woocommerce order is completed, but I can't get this hook to work. I can see this question asked many times.
Like here: https://wordpress.stackexchange.com/questions/134463/woocommerce-order-status-completed-action-hook-not-working
Here: https://wordpress.org/support/topic/woocommerce_order_status_completed-is-not-working
And here: https://wordpress.org/support/topic/woocommerce_order_status_completed-action-hook-not-working
But I cannot help myself with answers that these guys received.
I tried to add the action a few different ways:
add_action( 'woocommerce_order_status_completed', 'ikwoocommerceorderstatuscompleted_func');
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
add_action( 'woocommerce_order_status_completed', array(&$this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
Also tried with a class:
class IKHooks {
function __construct() {
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
}
public function ikwoocommerceorderstatuscompleted_func( $order_id ) {
}
}
I even tried to put the action outside of the class:
add_action( 'woocommerce_order_status_completed', array(IKHooks,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
None of these examples work. :(
Check the following steps before calling your hook.
Check if order completion email is sent.
Hook is properly registered in plugin file or theme functions.php
add_action( 'woocommerce_order_status_completed','callback_function_name' );
function callback_function_name(){
global $wp_filter;
print_r($wp_filter);
exit;
}
Check if the name of your callback function is in the hook array:
[woocommerce_order_status_completed] => Array
(
[10] => Array
(
[wc_paying_customer] => Array
(
[function] => wc_paying_customer
[accepted_args] => 1
)
[wc_downloadable_product_permissions] => Array
(
[function] => wc_downloadable_product_permissions
[accepted_args] => 1
)
[callback_function_name] => Array
(
[function] => callback_function_name
[accepted_args] => 3
)
)
)
If you find it then everything is ok, it means that probably there's an issue with your theme or functions.php file. Check for the hook or callback function in your files and then look for remove_action or remove_all_actions that's probably what's preventing your hook from being called.
You can also check in this way
add_action( 'woocommerce_order_status_completed', 'callback_function_name', 1);
Change the priority of your hook from 10 to 1 so it is called first than any other action or hook.
You can use this hook
add_action( 'woocommerce_order_status_changed', 'your_function', 99, 4 );
And the function will look like
function your_function( $order_id, $old_status, $new_status, $order ){
if( $new_status == "completed" ) {
//your code here
}
}
Hope this will be helpful.
I faced the similar issue earlier and solved it as:
Following code update the order status as completed
add_action( 'woocommerce_thankyou', 'your_wc_autocomplete_order' );
function your_wc_autocomplete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Once order is completed, if you want to do something, see the following code:
add_action('woocommerce_order_status_completed','payment_complete');
function payment_complete($order_id)
{
//global $items;
//$order = new WC_Order($order_id);
// do something ...
}
Hopefully, it will work :)
woocommerce_order_status_changed and woocommerce_order_status_completed actually work for me. After struggling for 2 days i realized that you just can't var_dump or var_export or print_r or whatever in the admin panel, it just won't work.
So if you are a newbie like me and thought those actions weren't working, just try triggering another action like sending a mail for example.
This code works:
function your_function( $order_id ){
$order = new WC_Order( $order_id );
$to_email = 'testing_mail#sample.com';
$payment = $order->get_payment_method_title();
$headers = 'From: Your Name <Your_site_mail#address.com>' . "\r\n";
wp_mail($to_email, 'subject', $payment, $headers );
}
add_action( 'woocommerce_order_status_completed', 'your_function');
Try using action hook woocommerce_order_status_changed.
It takes 4 parameters. order id, old status new status and order. Further code reference HERE
This may not be exactly suitable to your requirement, but seems to be worth of an alternative. Hope this helps.
I think you might be after this guy. woocommerce_payment_complete
function mysite_woocommerce_payment_complete( $order_id ) {
error_log( "Payment has been received for order $order_id", 0 );
}
add_action( 'woocommerce_payment_complete', 'mysite_woocommerce_payment_complete' );
I'm creating a plugin for wordpress and woocommerce. In my plugin, I've inserted an input box above the checkout form using code using 'woocommerce_before_checkout_form'. On completion of the order, I'd like to be able to add the value from that input to the order's meta data. to that end, I created this code in the functions.php file of my plugin:
add_action( 'woocommerce_checkout_update_order_meta', 'add_input_meta', 1, 2 );
function add_input_meta( $order_id, $posted ) {
$inputsData = $_POST['InputBox'];
update_post_meta( $order_id, 'my_key', $inputsData);
}
The problem is, it returns NULL every time. I created the code below to see what the value of $_POST and it came up with 'array(0) { }'
function debugthing( $content ) {
$content .=var_dump($_POST);
return $content;
die();
}
add_filter( 'the_content', 'debugthing' );
I've exhausted every idea I could ahve about what is causing this. can anyone help?
$_POST, even php://input return an empty array or absolutely nothing.
woocommerce_before_checkout_form is not the right hook to add input fields. For this hook is outside the form. This explains why you are getting null on $_POST
use any of the hook inside the <form in form-checkout.php#L35
call woocommerce_form_field to add fields...
next is you need to hook inside process_checkout() function.
a. woocommerce_after_checkout_validation - for input validations...
b. woocommerce_checkout_order_processed - order created, do your meta data addition...
// add form fields
add_action( 'woocommerce_checkout_before_customer_details', 'woocommerce_checkout_before_customer_details' );
function woocommerce_checkout_before_customer_details() {
$args = array(
'type' => 'text',
'label' => 'My Custom field',
'description' => 'This is custom field',
'placeholder' => '',
'required' => true,
);
woocommerce_form_field( 'InputBox' , $args ); // you can call woocommerce_form_field as many as you want...
}
// validate your form field(s)
add_action( 'woocommerce_after_checkout_validation', 'woocommerce_after_checkout_validation' );
function woocommerce_after_checkout_validation() {
// $_POST['InputBox'] will be visible here...
// do your validations here... forget this hook if you don't need to validate...
// wc_add_notice( __( 'Invalid message!', 'woocommerce' ), 'error' );
// call wc_add_notice if you want to invalidate the form.
}
add_action( 'woocommerce_checkout_order_processed', 'woocommerce_checkout_order_processed' );
function woocommerce_checkout_order_processed( $order_id ) {
// we now have $order_id, you can now add your meta data....
}
change your hook priority like this.
add_action( 'woocommerce_checkout_update_order_meta', 'add_input_meta', 99, 2 );
I'm developing a plugin to customise the woocommerce registration and trying to avoid direct editing of the core files.
I need to override or replace process_registration action in woocommerces includes/class-wc-form-handler.php file through my plugin.
add_action( 'init', array( $this, 'process_registration' ) );
I tried following links, but they didn't work. Also, the files mentioned on those pages doesn't exist on woocommerce current version. I also checked woocommerce documentation, but it seems they don't have a hook for that.
http://wordpress.org/support/topic/overriding-woocommerce_process_registration-in-child-theme-functionsphp
Woocommerce Hooks:
http://docs.woothemes.com/document/hooks/
I'd really appreciate any help!
Two options for that and considering that WC method starts like:
class WC_Form_Handler
public function __construct() {
add_action( 'init', array( $this, 'process_registration' ) );
}
public function process_registration() {
if ( ! empty( $_POST['register'] ) ) {
wp_verify_nonce( $_POST['register'], 'woocommerce-register' );
# etc
}
}
}
new WC_Form_Handler();
Add an init hook with top priority and duplicate then unset($_POST['register']). WC doesn't specify a priority, so it's running on 10, which is default.
add_action( 'init', function() { /* dup, unset, do your thing */ }, 1 ); // priority 1
Track down that evil anonymous object where Woo is hidding its hook, so that you can:
// pseudo code, go to WPSE for the real thing
remove_hook( 'init', 'woo_process_registration' );