Woo-commerce Booking - Fetch all available bookings based on Time Range - wordpress

I'm trying to fetch bookings based on time availability in wocommerce bookings by passing the time selection in below format:
2019-08-26 08:00 - 2019-08-26 11:00
$available_blocks = $booking_form->product->get_available_blocks( array(
'blocks' => $blocks_in_range,
'from' => $from,
'to' => $to));
foreach ( $available_blocks as $check ) {
if ( true === $booking_form->product->check_availability_rules_against_date( $check, '' )){
//Custom Added to fetch only blocks in selected range
if( $from >= reset($available_blocks) && $to <= end($available_blocks)){
$matches[] = $post_id;
break; // check passed
}
}
}
But, it's only working when I pass time in Hour only format(10:00 AM), When I add minute(10:30 AM) it is not returning any available bookings.
Full function for reference.
/**
* Get all available booking products
*
* #param string $start_date_raw YYYY-MM-DD format
* #param string $end_date_raw YYYY-MM-DD format
* #param int $quantity Number of people to book
* #param string $behavior Whether to return exact matches
* #return array Available post IDs
*/
function get_available_bookings( $start_date_raw, $end_date_raw, $quantity = 1, $behavior = 'default' ) {
$matches = array();
// Separate dates from times
$start_date = explode( ' ', $start_date_raw );
$end_date = explode( ' ', $end_date_raw );
// If time wasn't passed, define defaults.
if ( ! isset( $start_date[1] ) ) {
$start_date[1] = '00:00';
}
$start = explode( '-', $start_date[0] );
$args = array(
'wc_bookings_field_resource' => 0,
'wc_bookings_field_persons' => $quantity,
'wc_bookings_field_duration' => 1,
'wc_bookings_field_start_date_year' => $start[0],
'wc_bookings_field_start_date_month' => $start[1],
'wc_bookings_field_start_date_day' => $start[2],
);
// Loop through all posts
foreach ( $this->product_ids as $post_id ) {
if ( 'product' == get_post_type( $post_id ) ) {
$product = wc_get_product( $post_id );
if ( is_wc_booking_product( $product ) ) {
// Grab the duration unit
$unit = $product->is_type( 'accommodation-booking' ) ? 'night' : $product->get_duration_unit();
// Support time
if ( in_array( $unit, array( 'minute', 'hour' ) ) ) {
if ( ! empty( $start_date[1] ) ) {
$args['wc_bookings_field_start_date_time'] = $start_date[1];
}
}
if ( 'exact' === $behavior ) {
$duration = $this->calculate_duration( $start_date_raw, $end_date_raw, $product->get_duration(), $unit );
$args['wc_bookings_field_duration'] = $duration;
}
$booking_form = new WC_Booking_Form( $product );
$posted_data = $booking_form->get_posted_data( $args );
// All slots are available (exact match)
if ( true === $booking_form->is_bookable( $posted_data ) ) {
$matches[] = $post_id;
}
// Any slot between the given dates are available
elseif ( 'exact' !== $behavior ) {
$from = strtotime( $start_date_raw );
$to = strtotime( $end_date_raw );
$blocks_in_range = $booking_form->product->get_blocks_in_range( $from, $to );
// Arguments changed in WC Bookings 1.11.1
$available_blocks = $booking_form->product->get_available_blocks( array(
'blocks' => $blocks_in_range,
'from' => $from,
'to' => $to
) );
foreach ( $available_blocks as $check ) {
if ( true === $booking_form->product->check_availability_rules_against_date( $check, '' )){
$matches[] = $post_id;
break; // check passed
}
}
}
}
}
}
return $matches;
}

Related

How to make credits accrue not only for new reviews, but for all user reviews?

At the moment I'm using the code below, it only gives credits for 1 new user review... I tried to change the code, but all my attempts are unsuccessful... an example of what I want to do: a user leaves 10 reviews for one product, for each feedback he should receive 1 dollar, that is, 10 x 1 = 10 dollars. I want to set up so that credits are awarded not only for new reviews, but for all any user reviews. I would be very grateful for any help!
/**
* Process new product review action.
*
* #param int $comment_id comment_id.
* #param bool $comment_approved comment_approved.
* #param array $commentdata commentdata.
*/
public function new_product_review( $comment_id, $comment_approved, $commentdata ) {
if ( 'product' === get_post_type( absint( $commentdata['comment_post_ID'] ) ) ) {
if ( ! $this->is_enabled() || 1 !== $commentdata['comment_approved'] || get_comment_meta( $comment_id, 'wallet_transaction_id', true ) || get_post_meta( $commentdata['comment_post_ID'], "_woo_wallet_comment_commission_received_{$commentdata['user_id']}", true ) ) {
return;
}
$this->amount = apply_filters( 'woo_wallet_product_review_action_amount', $this->settings['amount'], $comment_id, $commentdata['user_id'] );
$product = wc_get_product( $commentdata['comment_post_ID'] );
if ( $this->amount && $product && apply_filters( 'woo_wallet_product_review_credit', true, $commentdata ) ) {
$transaction_id = woo_wallet()->wallet->credit( $commentdata['user_id'], $this->amount, sanitize_textarea_field( $this->settings['description'] ) );
update_comment_meta( $comment_id, 'wallet_transaction_id', $transaction_id );
update_post_meta( $commentdata['comment_post_ID'], "_woo_wallet_comment_commission_received_{$commentdata['user_id']}", true );
do_action( 'woo_wallet_after_product_review', $transaction_id, $comment_id );
}
}
}
/**
* Credit new product review.
*
* #param string $new_status new_status.
* #param string $old_status old_status.
* #param object $comment comment.
*/
public function woo_wallet_product_review_credit( $new_status, $old_status, $comment ) {
$product = wc_get_product( $comment->comment_post_ID );
if ( ! $this->is_enabled() || 'approved' !== $new_status || get_comment_meta( $comment->comment_ID, 'wallet_transaction_id', true ) || get_post_meta( $product->get_id(), "_woo_wallet_comment_commission_received_{$comment->user_id}", true ) ) {
return;
}
$this->amount = apply_filters( 'woo_wallet_product_review_action_amount', $this->settings['amount'], $comment->comment_ID, $comment->user_id );
if ( $this->amount && $product && apply_filters( 'woo_wallet_product_review_credit', true, $comment ) ) {
$transaction_id = woo_wallet()->wallet->credit( $comment->user_id, $this->amount, sanitize_textarea_field( $this->settings['description'] ) );
update_comment_meta( $comment->comment_ID, 'wallet_transaction_id', $transaction_id );
update_post_meta( $product->get_id(), "_woo_wallet_comment_commission_received_{$comment->user_id}", true );
do_action( 'woo_wallet_after_product_review', $transaction_id, $comment->comment_ID );
}
}
}

Remove percent coupon if discounted price of product is more than 10%

I need to remove / disable the coupon effect for products discounted by more than 10%.
At the moment I have something like this:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$excluded_categories = array( 'prod_category_name' );
// Initialize
$coupon_flag = false;
// Loop through applied coupons
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'percent_product' ) ) ) {
$coupon_flag = true;
break;
}
}
foreach( $cart->get_applied_coupons() as $coupon_code ) {
// Get the WC_Coupon object
$coupon = new WC_Coupon($coupon_code);
$coupon_amount = $coupon->get_amount(); // Get coupon amount
}
if ( $coupon_flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get product ID in
$product_id = $cart_item['product_id'];
// NOT contains the definite term
if ( ! has_term( $excluded_categories, 'product_cat', $product_id ) ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Get promo price
$promo_price = $cart_item['data']->get_price();
// Zniżka
$discount = 100 - (($promo_price * 100) / $regular_price);
$percentage = 10;
$percent_price = $regular_price - ($regular_price * ($percentage / 100));
if ($discount > $coupon_amount ) {
//$coupon->set_amount(0);
$cart->remove_coupon( 'coupon_name' );
}
if ( $percent_price < $promo_price ) {
$cart_item['data']->set_price( $regular_price );
} else {
$cart_item['data']->set_price( $promo_price );
}
}
}
}
}
At the moment, the code removes the coupon for the entire cart:
$cart->remove_coupon( 'coupon_name' );
Is there an option to remove the discount for the selected product from the cart?
I need something like:
$cart_item['data']->remove_coupon( 'coupon_name' );
Thank you so much!
Ok I added filter and it works perfect =)
add_filter( 'woocommerce_coupon_is_valid_for_product', 'exclude_product_from_product_promotions_frontend', 9999, 4 );
function exclude_product_from_product_promotions_frontend( $valid, $product, $coupon, $values ) {
$regular_price = $product->get_regular_price();
$promo_price = $product->get_price();
$discount = 100 - (($promo_price * 100) / $regular_price);
$coupon_amount = 10;
if ($discount > $coupon_amount ) {
$valid = false;
}
return $valid;
}

Mod a Wordpress Function to have 10 iteration per times

Im tryng to mod this function to make an update more powerful.
What im tryng to do is to mod this function:
add_action( 'wp_loaded', 'cron_revise_changed_listings' );
function cron_revise_changed_listings() {
global $wpdb;
if ( !isset( $_REQUEST['wplister_revise_all'] ) ) {
return;
}
$limit = isset( $_REQUEST['revise_limit'] ) ? intval( $_REQUEST['revise_limit'] ) : 10;
$listings = $wpdb->get_results("
SELECT id, account_id
FROM {$wpdb->prefix}ebay_auctions
WHERE status = 'changed'
ORDER BY id DESC
LIMIT {$limit}", ARRAY_A );
if ( empty( $listings ) ) {
die( json_encode( array( 'revised' => 0 ) ) );
}
$lm = new ListingsModel();
$revised = 0;
$last_account_id = false;
foreach ( $listings as $listing ) {
if ( $last_account_id != $listing['account_id'] ) {
$last_account_id = $listing['account_id'];
WPLE()->initEC( $listing['account_id'] );
}
$lm->reviseItem( $listing['id'], WPLE()->EC->session );
$revised++;
}
WPLE()->EC->closeEbay();
die( json_encode( array( 'revised' => $revised ) ) );
}
What i need to obtain is to repeat cycle for each, but with a step of 10 items per time so for revise 100 items it need only to do 10 cicles and not 100...someone have any ideas?

How to limit query in price filter

How to limit query to 6 in woocommerce product price filter short-code [products_by_price min="100" max="300"]? The code below is based on woocommerce product short-code which unfortunately does not support per_page. In this case I need to limit query to 6 to avoid showing all products.
add_shortcode( 'wc_products_price_range', 'wc_products_price_range' );
function wc_products_price_range( $atts, $content, $shortcode ) {
if ( class_exists( 'WooCommerce' ) ) {
$shortcodes = new WC_Shortcodes();
if ( is_array( $atts ) ) {
$min = (int) $atts['min'];
$max = (int) $atts['max'];
if ( $min && $max ) {
$and = "meta_value BETWEEN $min AND $max";
} else {
if ( $min ) {
$and = "meta_value >= $min";
} elseif ( $max ) {
$and = "meta_value <= $max";
}
}
if ( $and ) {
global $wpdb;
$query = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_price' AND $and";
$ids = $wpdb->get_col( $query );
if ( ! empty( $ids ) ) {
$atts['ids'] = implode( ",", $ids );
}
}
}
return $shortcodes->products( $atts );
}
}
After a quick scan of WC shortcode class I have came across this :
public static function products( $atts ) {
$atts = shortcode_atts( array(
'columns' => '4',
'orderby' => 'title',
'order' => 'asc',
'ids' => '',
'skus' => ''
), $atts );
it means you can pass 'column' attribute along with ids where you can limit posts per page.
and in this query :
$query = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_price' AND $and";
you can use limit 0,6 with order by clause.
Hope this helps.
OR
random rows:
SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;
or you can pass 'rand' to attributes in shortcode.

wordpress - Sortable custom fields columns

I added some custom fields (dates) in my admin columns. I try to make them sortable but in order to do that I need to convert them from string to date. My naive and simple code obviously doesn't work... Can someone point out my error(s) ?
add_action( 'pre_get_posts', 'orderby_date' );
function orderby_date( $query ) {
$orderby = $query->get( 'orderby');
if( 'start' == $orderby ) {
$query->set('meta_key','class_start');
$query->set('orderby',"STR_TO_DATE(meta_value,'%m/%d/%Y')");
}
}
This is what you are looking for:
add_filter( 'posts_clauses', 'manage_wp_posts_be_qe_posts_clauses', 1, 2 );
function manage_wp_posts_be_qe_posts_clauses( $pieces, $query ) {
global $wpdb;
if ( $query->is_main_query() && ( $orderby = $query->get( 'orderby' ) ) ) {
$order = strtoupper( $query->get( 'order' ) );
if ( ! in_array( $order, array( 'ASC', 'DESC' ) ) )
$order = 'ASC';
switch( $orderby ) {
case 'class_start':
$pieces[ 'join' ] .= " LEFT JOIN $wpdb->postmeta wp_rd ON wp_rd.post_id = {$wpdb->posts}.ID AND wp_rd.meta_key = 'class_start'";
$pieces[ 'orderby' ] = "STR_TO_DATE( wp_rd.meta_value,'%m/%d/%Y' ) $order, " . $pieces[ 'orderby' ];
break;
}
}
return $pieces;
}
You can read more about it here: http://wpdreamer.com/2014/04/how-to-make-your-wordpress-admin-columns-sortable/

Resources