Ask your WordPress questions! Pay money and get answers fast! (more info)

Remove order_pickup_location action from woocommerce_view_order WordPress

  • SOLVED

This is partly a continuation from my previous question
[[LINK href="http://www.wpquestions.com/question/showChrono/id/9204"]]Remove thankyou_page function from WooCommerce payment gateway[[/LINK]]
but the details are slightly different.

What I want to do now is remove an action called 'order_pickup_location' that is added by a plugin, called 'Local Pickup Plus'.

The action is added in the __construct method of the WC_Local_Pickup_Plus class, which extends SV_WC_Plugin as follows:
add_action( 'woocommerce_view_order', array( $this, 'order_pickup_location' ), 20 );
add_action( 'woocommerce_thankyou', array( $this, 'order_pickup_location' ), 20 );


The actual 'order_pickup_location' method is located in the WC_Shipping_Local_Pickup_Plus class, which extends WC_Shipping_Method.

This method outputs a formatted version of a pickup location address, which appears at an unhelpful location on the order details and thank you pages, so I want to relocate it using remove/add.

Eventually I will also need to move a similar function in the email template:
add_action( 'woocommerce_after_template_part', array( $this, 'email_pickup_location' ), 10, 3 );
but I expect that the answer to this question will address that also.

I know that I could just edit the hook in the add_action statements in the plugin in 5 seconds, and it works exactly as I want it to, but that's not maintainable, and I wouldn't learn anything ;)

Once again, I'm stuck on which class variable I need to reference in my remove action:
remove_action( 'woocommerce_view_order', array( $some_object, 'order_pickup_location' ), 20 );

I have duplicated my code from the last solution, and successfully retrieved the shipping object for the 'local_pickup_plus' shipping method using the WC_Shipping_Local_Pickup_Plus class, but I don't know if that's the right class/object to be using, given that the action is actually added in the WC_Local_Pickup_Plus class (using $this);

One other difference from the payment gateways is that shipping methods don't seem to be loaded on this page, so if I don't explicitly load them, using
$load_methods = $GLOBALS['woocommerce']->shipping->load_shipping_methods();
I don't have access to the shipping method objects.

I have successfully added the formatted pickup location to my desired spot, by adding a hook to my template, and using this code:

// Displaying pickup address location - works
add_action('yw_after_address_details', 'yw_display_pickup_details');
function yw_display_pickup_details( $order_id ){
$order = new WC_Order( $order_id );
$new_shipping_object = yw_get_shipping_object('WC_Shipping_Local_Pickup_Plus');
$new_shipping_object->order_pickup_location($order);
}
// get shipping object
function yw_get_shipping_object ( $classname ){
$load_methods = $GLOBALS['woocommerce']->shipping->load_shipping_methods();
foreach( (array) $GLOBALS['woocommerce']->shipping->shipping_methods as $key => $shipping_obj ){
if( $classname === get_class( $shipping_obj ) ){
$shipping_object = $shipping_obj;
}
}
return $shipping_object;
}


This is the order_pickup_location method from the WC_Shipping_Local_Pickup_Plus class

public function order_pickup_location( $order ) {
$pickup_locations = $this->get_order_pickup_locations( $order );
if ( count( $pickup_locations ) > 0 ) {
echo '<div>';
echo '<header class="title"><h3>' . _n( 'Pickup Location', 'Pickup Locations', count( $pickup_locations ), WC_Local_Pickup_Plus::TEXT_DOMAIN ) . '</h3></header>';
}
foreach ( $pickup_locations as $pickup_location ) {
$formatted_pickup_location = $this->get_formatted_address_helper( $pickup_location );
echo '<address>';
echo '<p>' . $formatted_pickup_location . '</p>';
echo '</address>';
}
if ( count( $pickup_locations ) > 0 ) {
echo '</div>';
}
}


I don't know if I should even be referencing shipping classes, or whether I need to go through the order itself. I think I'm really close, but now I'm just chasing my tail, because I don't know where to go with it.

Please let me know if you need more info. I have heaps more code and outputs if they can tell you what you need to know.

Thank you :)

Answers (1)

2014-01-26

Ross Wilson answers:

It looks like adding these functions ([[LINK href="https://github.com/herewithme/wp-filters-extras/"]]https://github.com/herewithme/wp-filters-extras/[[/LINK]]) and using them as described in the documentation (pretty simple) are the way you are going to have to go if the original WC_Shipping_Local_Pickup_Plus class is not stored as a global (you can check by searching through your code for "new WC_Shipping_Local_Pickup_Plus" and see what turns up.


Nikki comments:

Ok, so the only time there's a reference to 'new WC_Shipping_Local_Pickup_Plus' in the plugin is in the methods for the 'WC_Local_Pickup_Plus' class, in the following method:

private function get_local_pickup_plus() {

if ( ! is_object( $this->gateway_class ) ) {
$this->gateway_class = new WC_Shipping_Local_Pickup_Plus();
}

return $this->gateway_class;
}


I'm not 100% sure what this creates, but I don't think it's a global?

I'll have a look at the functions you suggested, thanks.


Ross Wilson comments:

This looks like its creating a single WC_Shipping_Local_Pickup_Plus class, but it is a private function, so not something you can access unfortunately. Looks like you will have to go with including the other suggested functions.


Nikki comments:

Done, thank you! That was nice and fast :)

So I copied the wp-filters-extras.php into my theme's functions.php and added these two lines
remove_filters_for_anonymous_class( 'woocommerce_view_order', 'WC_Local_Pickup_Plus', 'order_pickup_location', 20 );
remove_filters_for_anonymous_class( 'woocommerce_thankyou', 'WC_Local_Pickup_Plus', 'order_pickup_location', 20 );

And I suspect this handy function is going to come in handy many more times as well.

Can you confirm that the plugin did not create a global, based on the above method?

Would I have been able to address $this->gateway_class and remove it using my code, or was I eternally doomed with this approach?

Thanks.


Nikki comments:

Sorry, I overlapped with your reply. Thanks for clarifying, and thanks for your help.