-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No programatic way to add booking products to the cart #368
Comments
does priority low mean that I'm right and there is no way to add it to the cart from code? |
Well if somebody else comes along looking to solve this problem, here is how I've done it. Added this action: add_action('woocommerce_add_to_cart', array($this, 'process_safari_suggest_bookings'), 10, 6); And added these functions to my plugin: /**
* Add extra booking items to cart
* @since 1.0.0
*/
function process_safari_suggest_bookings($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data)
{
if (isset($_POST['_knepp_safari_suggest'])) {
// get data
$safaris = json_decode(stripslashes($_POST['_knepp_safari_suggest']), true);
$persons = isset($_POST['wc_bookings_field_persons']) ? $_POST['wc_bookings_field_persons'] : 1;
// add to cart
foreach ($safaris as $safari) {
$this->add_safari_to_cart($safari, $persons);
}
// clear value so its only run once this request
unset($_POST['_knepp_safari_suggest']);
}
}
/**
* Add bookable product to cart
* Code taken from WC_Booking_Cart_Manager->add_cart_item_data()
* @since 1.0.0
*/
private function add_safari_to_cart($safari, $persons)
{
$product_id = $safari['product_id'];
$quantity = 1; // not used by bookable products
$start_date_time = $safari['wc_bookings_field_start_date_time'];
$simulated_post = array(
'wc_bookings_field_start_date_time' => $start_date_time,
'wc_bookings_field_persons' => $persons,
);
$cart_item_meta = array();
$product = wc_get_product($product_id);
if (!is_wc_booking_product($product)) {
return;
}
$cart_item_meta['booking'] = wc_bookings_get_posted_data($simulated_post, $product);
$cart_item_meta['booking']['_cost'] = WC_Bookings_Cost_Calculation::calculate_booking_cost($cart_item_meta['booking'], $product);
if ($cart_item_meta['booking']['_cost'] instanceof WP_Error) {
throw new Exception($cart_item_meta['booking']['_cost']->get_error_message());
}
// Create the new booking
$new_booking = $this->create_booking_from_cart_data($cart_item_meta, $product_id);
// Store in cart
$cart_item_meta['booking']['_booking_id'] = $new_booking->get_id();
// Schedule this item to be removed from the cart if the user is inactive.
$this->schedule_cart_removal($new_booking->get_id());
WC()->cart->add_to_cart($product_id, $quantity, 0, array(), $cart_item_meta);
}
/**
* Create booking from cart data
*
* @param $cart_item_meta
* @param $product_id
* @param string $status
*
* @return WC_Booking
*/
private function create_booking_from_cart_data($cart_item_meta, $product_id, $status = 'in-cart')
{
// Create the new booking
$new_booking_data = array(
'product_id' => $product_id, // Booking ID
'cost' => $cart_item_meta['booking']['_cost'], // Cost of this booking
'start_date' => $cart_item_meta['booking']['_start_date'],
'end_date' => $cart_item_meta['booking']['_end_date'],
'all_day' => $cart_item_meta['booking']['_all_day'],
'local_timezone' => $cart_item_meta['booking']['_local_timezone'],
);
// Check if the booking has resources
if (isset($cart_item_meta['booking']['_resource_id'])) {
$new_booking_data['resource_id'] = $cart_item_meta['booking']['_resource_id']; // ID of the resource
}
// Checks if the booking allows persons
if (isset($cart_item_meta['booking']['_persons'])) {
$new_booking_data['persons'] = $cart_item_meta['booking']['_persons']; // Count of persons making booking
}
$new_booking = get_wc_booking($new_booking_data);
$new_booking->create($status);
return $new_booking;
}
/**
* Schedule booking to be deleted if inactive
*/
public function schedule_cart_removal($booking_id)
{
$minutes = apply_filters('woocommerce_bookings_remove_inactive_cart_time', 60);
/**
* If this has been emptied, or set to 0, it will just exit. This means that in-cart bookings will need to be manually removed.
* Also take note that if the $minutes var is set to 5 or less, this means that it is possible for the in-cart booking to be
* removed before the customer is able to check out.
*/
if (empty($minutes)) {
return;
}
$timestamp = time() + MINUTE_IN_SECONDS * (int) $minutes;
wp_schedule_single_event($timestamp, 'wc-booking-remove-inactive-cart', array($booking_id));
} And the way it works is that I've used the slots api to generate a list of options, and then use some angular code to json encode the values into a hidden field on booking form so that it gets submitted on the add to cart. The site im building this on is elementor, jet woo builder, based and it works with the ajax add to cart as well. From a plugin point of view, if I could have just got a way to access the instantiated However, it is just instantiated by the main class as a simple new WC_Booking_Cart_Manager(), without assigning to to a variable, and no way to get a reference to it. |
I put a modification into it where I'm passing in a random number id now and stuffing that in a transient. Otherwise, sometimes it would end up adding in multiple times to the cart. Here is the updated function: /**
* Add extra booking items to cart
* @since 1.0.0
*/
function process_safari_suggest_bookings($cart)
{
if (isset($_POST['_knepp_safari_suggest_id']) && isset($_POST['_knepp_safari_suggest'])) {
$safariId = sanitize_text_field($_POST['_knepp_safari_suggest_id']);
if (false === get_transient($safariId)) {
set_transient($safariId, true, 60);
$safaris = json_decode(stripslashes($_POST['_knepp_safari_suggest']), true);
$persons = isset($_POST['wc_bookings_field_persons']) ? $_POST['wc_bookings_field_persons'] : 1;
foreach ($safaris as $safari) {
$this->add_safari_to_cart($safari, $persons);
}
}
}
} |
@rtpHarry thank you for the report.
No, the priority low means that the ticket does not greatly impact the plugin and the users. Hence, it should be prioritized as "low".
I'm glad to know that you found a solution. Thanks for sharing the details.
The plugin never required assigning variables to initiated classes so far. Your case is unique so I recommend you initialize the required class and assign in a variable in your custom plugin/functions file. Q: If you feel there are no code changes required in the Bookings plugin, should I go ahead and close the ticket? |
I cannot instantiate my own copy of At the moment I have a working solution but it is not a good solution as I have had to adopt chunks of the plugin code to make it work. It would be better if there was an API to add bookings to the cart, or a way to get access to the At the moment, if you change any parts of your plugin, then my code could break, so it is a brittle solution to the problem. |
Hey, I have the same request and ended up almost with the same solution, should've googled first ;) |
What I expected
I want to be able to add the items to the cart from PHP code.
This is because I want to be able to show related safaris to go alongside my accommodation bookings. The user can select which safari they are interested in during their stay, and add them as they add the booking to the cart.
I've built the whole thing, right down to the last bit where I need to add it to the cart.
I have the required data to identify it but there doesn't seem to be any code that I can access. Its either fenced off inside other classes, or in a class that registers tons of actions and filters in its constructor so cannot be used, or relies on $GET or $POST.
I just want a simple way to pass in the required bits of meta and say add to cart.
It's looking like I'm going to have to copy chunks of the internal code to do this which is going to be time consuming and make my code brittle.
What happened instead
Can't find any api that is accessible that I can use to add a bookable product to the cart.
Steps to reproduce the issue
I wrote this and hooked it to
woocommerce_add_to_cart
but the page reloads and the products are not in the cart.The text was updated successfully, but these errors were encountered: