I am trying to create an API functions for mobile to get shipping methods from WordPress WooCommerce. This is my code:
public function get_shipping($request){
$params = (array) json_decode(file_get_contents('php://input'), TRUE);
$state = $params['state'];
$country = $params['country'];
global $woocommerce;
$woocommerce->cart->empty_cart();
foreach ($params['line_items'] as $item) {
if((int) $item["variation_id"] > 0 ){
$woocommerce->cart->add_to_cart(
(int) $item["id"],
(int) $item["quantity"],
$item["variation_id"]);
} else {
$woocommerce->cart->add_to_cart(
(int) $item["id"],
(int) $item["quantity"]);
}
}
$package = $woocommerce->cart->get_shipping_packages();
$delivery_zones = (Array) WC_Shipping_Zones::get_zones();
$new_delivery_zones = Array();
foreach ($delivery_zones as $zone) {
$z_object = (Array) $zone;
$new_shippings = Array();
foreach ($z_object["shipping_methods"] as $shipping) {
$s_item = Array();
$objects = (Array) $shipping;
foreach ($objects as $key => $value) {
if($key != "instance_form_fields") {
$s_item[$key] = $value;
}else{
$f_item = Array();
$new_form_fields = Array();
$form_fields = (Array) $value;
foreach ($form_fields as $keyi => $valuei) {
$valuei["name"] = $keyi;
$f_item[$keyi] = $valuei;
array_push($new_form_fields, $valuei);
}
$s_item["instance_form_fields"] = $new_form_fields;
}
}
array_push($new_shippings, $s_item);
}
$z_object["shipping_methods"] = null;
$z_object["shipping_methods"] = $new_shippings;
array_push($new_delivery_zones, $z_object);
}
$correct_zone = null;
foreach ($new_delivery_zones as $zone) {
foreach ($zone["zone_locations"] as $location) {
$splits = explode(":",$location-> code);
if(count($splits) > 1){
$country = $splits[0];
$code = $splits[1];
if($country == $country && $code == $state ){
$correct_zone = $zone;
}
}
}
}
if($correct_zone == null)
return $correct_zone;
$package['destination']['country'] = $country;
$package['destination']['state'] = (int) $state;
$package['destination']['country'] = $country;
$new_shipping_method = Array();
foreach ($correct_zone["shipping_methods"] as $shipping_method) {
if (class_exists($shipping_method["id"])) {
$class = new $shipping_method["id"]();
$class->calculate_shipping_for_package($package);
foreach ($class->rates as $rate) {
array_push($shipping_method["rates"], Array(
"cost" => $rate->cost,
"label" => $rate->label,
"method_id" => $rate->method_id
));
}
// error_log(print_r($class->rates, true));
array_push($new_shipping_method, $shipping_method);
}else{
array_push($new_shipping_method, $shipping_method);
}
}
$correct_zone["shipping_methods"] = $new_shipping_method;
return $correct_zone;
}
and I'm reading this post
BUT I did not understand where the problem is, Because it does not work properly and its calculated prices do not match post plugins.
Please Please Please give me the correct code
thank you very much
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;
}
Hi we are trying to sort the Woo Cart by Main product category and list under the products in that category. Like below:
Wheel Parts
spokes 12
Tyre's
Frame
Y Frame
X Frame
Z Frame
Seat
Seat 1
Seat 2
We have managed to get to display by cat order but it is not ordering them into Main Cat -> Sub Cat
We have the below code and trying to order cart array by cat and sub cat
add_action( 'woocommerce_cart_loaded_from_session', function() {
global $woocommerce;
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$terms = wp_get_post_terms($item['data']->id, 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->name;
}
natsort( $products_in_cart );
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $woocommerce->cart->cart_contents[ $cart_key ];
}
$woocommerce->cart->cart_contents = $cart_contents;
}, 100 );
Any one have any ideas please?
Your code was correct but you had just natsort which returning 1 is causing the issue. You also need to sort categories by menu order. Please check the below code working perfectly.
add_action( 'woocommerce_cart_loaded_from_session', function() {
global $woocommerce;
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$terms = wp_get_post_terms($item['data']->id, 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->term_id;
}
// $categories = get_terms( 'product_cat', 'orderby=menu_order&hide_empty=1' );
asort($products_in_cart);
$cat_array = array();
foreach ($products_in_cart as $key => $value) {
$cat_array[$key] =get_term_by('id', $value, 'product_cat');
}
$mai_cat = [];
$i=0;
foreach ($cat_array as $parent_key => $parent_value) {
if($parent_value->parent == 0)
{
$mai_cat[$parent_key] = $parent_value->term_id;
foreach ($cat_array as $parent_key_sub => $parent_value_sub) {
if($parent_value_sub->parent == $parent_value->term_id)
{
$mai_cat[$parent_key_sub] = $parent_value_sub->term_id;
}
}
}
}
$cart_contents = array();
foreach ( $mai_cat as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $woocommerce->cart->cart_contents[ $cart_key ];
}
$woocommerce->cart->cart_contents = $cart_contents;
}, 100 );
Tested and works well
I have a query that receive some array parameters without any ideas how rows there is. It must return contents with all filters (AND clause), and one or more categories (OR clause).
I can't get results I'd like because parentheses are not a the good place. I should got this SQL rendering:
WHERE (
f3_.idfilter = '87'
AND f5_.idfilter = '90'
AND f7_.idfilter = '154'
AND f9_.idfilter = '165'
)
AND (
c0_.content_category_idcontent_category = 1
OR c0_.content_category_idcontent_category = 3
)
and got this instead:
WHERE (
(
f3_.idfilter = '87'
AND f5_.idfilter = '90'
AND f7_.idfilter = '154'
AND f9_.idfilter = '165'
AND c0_.content_category_idcontent_category = 1
)
OR c0_.content_category_idcontent_category = 3
)
My code:
public function getContentByFiltersAjax($categs, $filters, $offset, $limit) {
$filtersTab = explode(',', $filters);
$query = $this->createQueryBuilder('c');
for ($i = 1; $i <= count($filtersTab); $i++) {
$query = $query
->leftJoin('c.filterfilter', 'f' . $i)
->andWhere('f' . $i . '.idfilter = :filter_idfilter' . $i)
->setParameter('filter_idfilter' . $i, $filtersTab[$i - 1]);
}
$categsTab = explode(',', $categs);
if(sizeof($categsTab) > 1) {
$expr = $query->expr();
$categsTab = explode(',', $categs);
foreach ($categsTab as $key => $value) {
if($key === 0){
$query->andWhere($expr->eq('c.contentCategorycontentCategory', $value));
} else {
$query->orWhere($expr->eq('c.contentCategorycontentCategory', $value));
}
}
} else {
$query
->andWhere('c.contentCategorycontentCategory = :category')
->setParameter('category', $categs);
}
$query
->andWhere('c.status = :status')
->setParameter('status', 'publie');
$query->orderBy('editor.plan', 'DESC');
$query->addOrderBy('c.creationDate', 'DESC');
$query
->setFirstResult($offset)
->setMaxResults($limit);
$result = $query->distinct()->getQuery()->getResult();
return $result;
}
You put the orWhere's inside 1 andWhere like this:
$query->andWhere(
$query->expr->orX(
$query->expr->eq('c.contentCategorycontentCategory', $value1),
$query->expr->eq('c.contentCategorycontentCategory', $value2)
)
);
Or in your foreach loop:
$orX = $query->expr->orX();
foreach ($categsTab as $value) {
$orX->add($query->expr->eq('c.contentCategorycontentCategory', $value));
}
$query->andWhere($orX);
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;
}
My website is not working properly. I get this error:
/var/www/vhosts/xyz.com.tr/httpdocs/wp-includes/wp-db.php on line 1890
Following is the code on those lines. What is the problem in this code that it throws out an error?
// Return number of rows affected
$return_val = $this->rows_affected;
} else {
$num_rows = 0;
if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
**while ( $row = mysqli_fetch_object( $this->result ) ) {
$this->last_result[$num_rows] = $row;
$num_rows++;**
}
} elseif ( is_resource( $this->result ) ) {
while ( $row = mysql_fetch_object( $this->result ) ) {
$this->last_result[$num_rows] = $row;
$num_rows++;
}
}
// Log number of rows the query returned
// and return number of rows selected
$this->num_rows = $num_rows;
$return_val = $num_rows;
}
return $return_val;
}
/**