Reputation: 25
I need to adding to cart woocommerce booking product, if i writing this code, i have false Or where normal documentation for this plugin?
global $woocommerce; $added = $woocommerce->cart->add_to_cart($product_id);
Upvotes: 1
Views: 841
Reputation: 13125
I know this is an old post but for anyone else that is trying to do this, the short answer is that its not supported out of the box.
The code below is not a drop in solution to the problem, but a good starting point for developers to implement their own solution.
I wanted to display some related safaris to go alongside an accommodation product page, so I needed a way to add them into the cart from a different products page.
This is just a part of the plugin, the php side of it. If you look at process_safari_suggest_bookings
then you will see that I'm augmenting the normal add to cart postback with an extra field with an array of other items I want to also add to the cart. This is done in the angular web component that I set up to display and collect the selected safari products (not included here as not relevant to actually adding bookable products to the cart).
I wrote this a while ago, but from memory, while investigating it, I found that the built in code was not actually accessible from outside of the plugin, so some bits of the WooCommerce Bookings code had to be adopted and placed in my plugin, so that it could build the data structure and add it to the cart correctly.
Good luck!
Code:
<?php
/**
* Plugin Name: WooCommerce Bookings Safari Suggest
* Plugin URI: https://runthings.dev/
* Description: Suggests safaris based on selected accommodation booking dates.
* Version: 1.4.0
* Author: Matthew Harris, runthings.dev
* Author URI: https://runthings.dev/
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
class Runthings_WC_Bookings_Safari_Suggest
{
public function __construct()
{
add_action('wp', array($this, 'maybe_display'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
add_action('woocommerce_after_calculate_totals', array($this, 'process_safari_suggest_bookings'));
add_filter('script_loader_tag', array($this, 'add_type_attribute'), 10, 3);
add_shortcode('runthings_safari_suggest', array($this, 'safari_suggest_shortcode'));
}
/**
* Only display the safari suggest web component on the product page for accommodation products
* @since 1.0.0
*/
public function maybe_display()
{
$product = wc_get_product();
if (
is_product()
&& is_a($product, 'WC_Product_Accommodation_Booking')
) {
add_action('woocommerce_before_add_to_cart_button', array($this, 'display'), 10);
}
}
/**
* Display the safari suggest web component in the add to cart form
* @since 1.0.0
*/
public function display()
{
// Search for the template in the active theme, and fallback to plugin directory if not found
$template_path = locate_template('runthings-wc-bookings-safari-suggest/display.php');
if (!$template_path) {
// Fallback to plugin directory
$template_path = plugin_dir_path(__FILE__) . 'templates/display.php';
}
if (file_exists($template_path)) {
include($template_path);
}
}
/**
* Shortcode callback
* @since 1.0.0
*/
public function safari_suggest_shortcode()
{
$domain = $this->get_rest_domain();
return '<knepp-safari-suggest rest-domain="' . $domain . '"></knepp-safari-suggest>';
}
/**
* Enqueue scripts conditionally
* @since 1.0.0
*/
public function enqueue_scripts()
{
if ((defined('WP_DEBUG') && WP_DEBUG) || (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG)) {
// WP_DEBUG or SCRIPT_DEBUG is true, enqueue debug versions
$debug_path = 'src/safari-suggest-web-component/dist/knepp-safari-suggest-web-component/';
wp_enqueue_script('runthings-runtime', plugin_dir_url(__FILE__) . $debug_path . 'runtime.js', array('jquery'), '1.0', true);
wp_enqueue_script('runthings-polyfills', plugin_dir_url(__FILE__) . $debug_path . 'polyfills.js', array('runthings-runtime'), '1.0', true);
wp_enqueue_script('runthings-vendor', plugin_dir_url(__FILE__) . $debug_path . 'vendor.js', array('runthings-polyfills'), '1.0', true);
wp_enqueue_script('runthings-main', plugin_dir_url(__FILE__) . $debug_path . 'main.js', array('runthings-vendor'), '1.0', true);
wp_enqueue_style('runthings-styles', plugin_dir_url(__FILE__) . $debug_path . 'styles.css', array(), '1.0', 'all');
} else {
// Neither WP_DEBUG nor SCRIPT_DEBUG is true, enqueue minified versions
wp_enqueue_script('runthings-safari-suggest', plugin_dir_url(__FILE__) . 'dist/runthings-safari-suggest.min.js', array('jquery'), '1.0', true);
wp_enqueue_style('runthings-safari-suggest', plugin_dir_url(__FILE__) . 'dist/runthings-safari-suggest.min.css', array(), '1.0', 'all');
}
}
/**
* Add type="module" to script tags
* @since 1.0.0
*/
function add_type_attribute($tag, $handle, $src)
{
// if not your script, do nothing and return original $tag
if (!in_array($handle, ['runthings-runtime', 'runthings-polyfills', 'runthings-vendor', 'runthings-main'])) {
return $tag;
}
// change the script tag by adding type="module" and return it.
$tag = '<script type="module" src="' . esc_url($src) . "\"></script>\n";
return $tag;
}
/**
* Get the domain to use in rest calls
* @since 1.0.0
*/
public function get_rest_domain()
{
// Sanitize the host using a regular expression to allow only valid characters in a domain name
$sanitized_host = preg_replace('/[^a-zA-Z0-9-.:]/', '', $_SERVER['HTTP_HOST']);
$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? "https" : "http";
return $protocol . "://" . $sanitized_host;
}
/**
* 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 = $this->get_persons_from_post();
if (!is_array($safaris)) {
return;
}
foreach ($safaris as $safari) {
$this->add_safari_to_cart($safari, $persons);
}
}
}
}
/**
* 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));
}
/**
* Extract the persons from the $_POST data
*/
private function get_persons_from_post()
{
$persons = 1;
if (isset($_POST['_knepp_safari_suggest_people'])) {
$decodedPersons = json_decode(stripslashes($_POST['_knepp_safari_suggest_people']), true);
$persons = intval($decodedPersons);
} else if (isset($_POST['wc_bookings_field_persons'])) {
$persons = intval($_POST['wc_bookings_field_persons']);
}
return $persons;
}
}
// Instantiate the class
$runthings_wc_bookings_safari_suggest = new Runthings_WC_Bookings_Safari_Suggest();
Upvotes: 0
Reputation: 11
// add the below code in a in functions.php of your theme.
add_filter( 'woocommerce_add_cart_item_data', array( $this, 'wdm_add_cities_to_cart' ), 11, 2 );
// the function accepts two parameters, the cart data and the product id
public function wdm_add_cities_to_cart( $cart_item_meta, $product_id ) {
// let's consider that the user is logged in
$user_id = get_current_user_id();
if( 0 != $user_id)
{
// set the values as bookings meta
$cart_item_meta['booking']['From'] = get_user_meta( $user_id, 'FROM', true );
$cart_item_meta['booking']['To'] = get_user_meta( $user_id, 'TO', true );
}
return $cart_item_meta;
}
Upvotes: 0
Reputation: 11
As, per my understanding i think bookable products meant to be book only. For that what you need to do is use this piece of code to do this pragmatically.
create_wc_booking( $product_id, $new_booking_data = array(), $status = 'confirmed', $exact = false )
1 Product ID: The id of the bookable product which you are creating a new booking for.
2.New Booking data: Array of booking data.
3.Status: Status of the new booking. Valid statuses include: ‘unpaid’, ‘pending’, ‘confirmed’, ‘cancelled’, ‘complete’
4.Exact: true or false – If false, the function will look for the next available slot after your start date, if the date you tried to book is unavailable.
Upvotes: 0