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?
Related
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;
}
the following code: Set product sale price programmatically in WooCommerce 3 works perfectly.
Also its continuation: Set programmatically product sale price and cart item prices in Woocommerce 3.
However I'd like to exclude an user role from this function altogether, how can I do that?
I added the following to the code above to no avail:
if ( ! wc_current_user_has_role( 'trader' ) ) return $product->get_regular_price();
Thanks
After asking around and trying it out, the following code manages to achieve what I need. For future reference if someone else needs it:
// Generating dynamically the product "regular price"
add_filter( 'woocommerce_product_get_regular_price', 'custom_dynamic_regular_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_regular_price', 'custom_dynamic_regular_price', 10, 2 );
function custom_dynamic_regular_price( $regular_price, $product ) {
if( empty($regular_price) || $regular_price == 0 )
return $product->get_price();
else
return $regular_price;
}
// Generating dynamically the product "sale price"
add_filter( 'woocommerce_product_get_sale_price', 'custom_dynamic_sale_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_sale_price', 'custom_dynamic_sale_price', 10, 2 );
function custom_dynamic_sale_price( $sale_price, $product ) {
$user = wp_get_current_user();
$rate = 0.9;
if( in_array( 'trader', (array) $user->roles ) ) {
return $product->get_regular_price() * $rate;
}
else
{
if( empty($sale_price) || $sale_price == 0 )
return $product->get_regular_price() * $rate;
else
return $sale_price;
}
};
// Displayed formatted regular price + sale price
add_filter( 'woocommerce_get_price_html', 'custom_dynamic_sale_price_html', 20, 2 );
function custom_dynamic_sale_price_html( $price_html, $product ) {
if( $product->is_type('variable') ) return $price_html;
$user = wp_get_current_user();
if( in_array( 'trader', (array) $user->roles ) ) {
$price_html = wc_price($product->get_regular_price() );
return $price_html;
}
else
{
$price_html = wc_format_sale_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ), wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) ) ) . $product->get_price_suffix();
return $price_html;
}
}
add_action( 'woocommerce_before_calculate_totals', 'set_cart_item_sale_price', 20, 1 );
function set_cart_item_sale_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Iterate through each cart item
foreach( $cart->get_cart() as $cart_item ) {
$price = $cart_item['data']->get_sale_price(); // get sale price
$cart_item['data']->set_price( $price ); // Set the sale price
}
}
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;
}
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.
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/