/** * Output widget. * * @see WP_Widget * * @param array $args * @param array $instance */ public function widget($args, $instance) { global $wp, $wp_the_query; if (!is_post_type_archive('product') && !is_tax(get_object_taxonomies('product'))) { return; } if (!$wp_the_query->post_count) { return; } $min_price = isset($_GET['min_price']) ? esc_attr($_GET['min_price']) : ''; $max_price = isset($_GET['max_price']) ? esc_attr($_GET['max_price']) : ''; wp_enqueue_script('wc-price-slider'); // Find min and max price in current result set $prices = $this->get_filtered_price(); $min = floor($prices->min_price); $max = ceil($prices->max_price); if ($min === $max) { return; } $this->widget_start($args, $instance); if ('' === get_option('permalink_structure')) { $form_action = remove_query_arg(array('page', 'paged'), add_query_arg($wp->query_string, '', home_url($wp->request))); } else { $form_action = preg_replace('%\\/page/[0-9]+%', '', home_url(trailingslashit($wp->request))); } /** * Adjust max if the store taxes are not displayed how they are stored. * Min is left alone because the product may not be taxable. * Kicks in when prices excluding tax are displayed including tax. */ if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $class_max = $max; foreach ($tax_classes as $tax_class) { if ($tax_rates = WC_Tax::get_rates($tax_class)) { $class_max = $max + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($max, $tax_rates)); } } $max = $class_max; } echo '<form method="get" action="' . esc_url($form_action) . '"> <div class="price_slider_wrapper"> <div class="price_slider" style="display:none;"></div> <div class="price_slider_amount"> <input type="text" id="min_price" name="min_price" value="' . esc_attr($min_price) . '" data-min="' . esc_attr(apply_filters('woocommerce_price_filter_widget_min_amount', $min)) . '" placeholder="' . esc_attr__('Min price', 'woocommerce') . '" /> <input type="text" id="max_price" name="max_price" value="' . esc_attr($max_price) . '" data-max="' . esc_attr(apply_filters('woocommerce_price_filter_widget_max_amount', $max)) . '" placeholder="' . esc_attr__('Max price', 'woocommerce') . '" /> <button type="submit" class="button">' . __('Filter', 'woocommerce') . '</button> <div class="price_label" style="display:none;"> ' . __('Price:', 'woocommerce') . ' <span class="from"></span> — <span class="to"></span> </div> ' . wc_query_string_form_fields(null, array('min_price', 'max_price'), '', true) . ' <div class="clear"></div> </div> </div> </form>'; $this->widget_end($args); }
/** * Constructor for the cart class. Loads options and hooks in the init method. */ public function __construct() { $this->prices_include_tax = wc_prices_include_tax(); $this->round_at_subtotal = get_option('woocommerce_tax_round_at_subtotal') == 'yes'; $this->tax_display_cart = get_option('woocommerce_tax_display_cart'); $this->dp = wc_get_price_decimals(); $this->display_totals_ex_tax = $this->tax_display_cart == 'excl'; $this->display_cart_ex_tax = $this->tax_display_cart == 'excl'; add_action('wp_loaded', array($this, 'init')); // Get cart after WP and plugins are loaded. add_action('wp', array($this, 'maybe_set_cart_cookies'), 99); // Set cookies add_action('shutdown', array($this, 'maybe_set_cart_cookies'), 0); // Set cookies before shutdown and ob flushing add_action('woocommerce_add_to_cart', array($this, 'calculate_totals'), 20, 0); add_action('woocommerce_applied_coupon', array($this, 'calculate_totals'), 20, 0); }
/** * Get discount amount for a cart item * * @param float $discounting_amount Amount the coupon is being applied to * @param array|null $cart_item Cart item being discounted if applicable * @param boolean $single True if discounting a single qty item, false if its the line * @return float Amount this coupon has discounted */ public function get_discount_amount($discounting_amount, $cart_item = null, $single = false) { $discount = 0; if ($this->is_type('fixed_product')) { $discount = $discounting_amount < $this->coupon_amount ? $discounting_amount : $this->coupon_amount; // If dealing with a line and not a single item, we need to multiple fixed discount by cart item qty. if (!$single && !is_null($cart_item)) { // Discount for the line. $discount = $discount * $cart_item['quantity']; } } elseif ($this->is_type(array('percent_product', 'percent'))) { $discount = round($discounting_amount / 100 * $this->coupon_amount, WC()->cart->dp); } elseif ($this->is_type('fixed_cart')) { if (!is_null($cart_item)) { /** * This is the most complex discount - we need to divide the discount between rows based on their price in * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows * with no price (free) don't get discounted. * * Get item discount by dividing item cost by subtotal to get a % */ $discount_percent = 0; if (WC()->cart->subtotal_ex_tax) { // Uses price inc tax if prices include tax to work around https://github.com/woothemes/woocommerce/issues/7669 $discount_percent = $cart_item['data']->get_price() * $cart_item['quantity'] / (wc_prices_include_tax() ? WC()->cart->subtotal : WC()->cart->subtotal_ex_tax); } $discount = min($this->coupon_amount * $discount_percent / $cart_item['quantity'], $discounting_amount); } else { $discount = min($this->coupon_amount, $discounting_amount); } } // Handle the limit_usage_to_x_items option if ($this->is_type(array('percent_product', 'fixed_product')) && !is_null($cart_item)) { if ('' === $this->limit_usage_to_x_items) { $qty = $cart_item['quantity']; } else { $qty = min($this->limit_usage_to_x_items, $cart_item['quantity']); $this->limit_usage_to_x_items = max(0, $this->limit_usage_to_x_items - $qty); } if ($single) { $discount = $discount * $qty / $cart_item['quantity']; } else { $discount = $discount / $cart_item['quantity'] * $qty; } } return apply_filters('woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this); }
/** * Price Filter post filter. * * @param array $filtered_posts * @return array */ public function price_filter($filtered_posts = array()) { global $wpdb; if (isset($_GET['max_price']) || isset($_GET['min_price'])) { $matched_products = array(); $min = isset($_GET['min_price']) ? floatval($_GET['min_price']) : 0; $max = isset($_GET['max_price']) ? floatval($_GET['max_price']) : 9999999999; // If displaying prices in the shop including taxes, but prices don't include taxes.. if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); foreach ($tax_classes as $tax_class) { $tax_rates = WC_Tax::get_rates($tax_class); $min_class = $min - WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($min, $tax_rates)); $max_class = $max - WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($max, $tax_rates)); $matched_products_query = apply_filters('woocommerce_price_filter_results', $wpdb->get_results($wpdb->prepare("\n\t\t\t\t\t\tSELECT DISTINCT ID, post_parent, post_type FROM {$wpdb->posts}\n\t\t\t\t\t\tINNER JOIN {$wpdb->postmeta} pm1 ON ID = pm1.post_id\n\t\t\t\t\t\tINNER JOIN {$wpdb->postmeta} pm2 ON ID = pm2.post_id\n\t\t\t\t\t\tWHERE post_type IN ( 'product', 'product_variation' )\n\t\t\t\t\t\tAND post_status = 'publish'\n\t\t\t\t\t\tAND pm1.meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price')))) . "')\n\t\t\t\t\t\tAND pm1.meta_value BETWEEN %f AND %f\n\t\t\t\t\t\tAND pm2.meta_key = '_tax_class'\n\t\t\t\t\t\tAND pm2.meta_value = %s\n\t\t\t\t\t", $min_class, $max_class, sanitize_title($tax_class)), OBJECT_K), $min_class, $max_class); if ($matched_products_query) { foreach ($matched_products_query as $product) { if ($product->post_type == 'product') { $matched_products[] = $product->ID; } if ($product->post_parent > 0) { $matched_products[] = $product->post_parent; } } } } } else { $matched_products_query = apply_filters('woocommerce_price_filter_results', $wpdb->get_results($wpdb->prepare("\n\t\t\t\t\tSELECT DISTINCT ID, post_parent, post_type FROM {$wpdb->posts}\n\t\t\t\t\tINNER JOIN {$wpdb->postmeta} pm1 ON ID = pm1.post_id\n\t\t\t\t\tWHERE post_type IN ( 'product', 'product_variation' )\n\t\t\t\t\tAND post_status = 'publish'\n\t\t\t\t\tAND pm1.meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price')))) . "')\n\t\t\t\t\tAND pm1.meta_value BETWEEN %d AND %d\n\t\t\t\t", $min, $max), OBJECT_K), $min, $max); if ($matched_products_query) { foreach ($matched_products_query as $product) { if ($product->post_type == 'product') { $matched_products[] = $product->ID; } if ($product->post_parent > 0) { $matched_products[] = $product->post_parent; } } } } $matched_products = array_unique($matched_products); // Filter the id's if (0 === sizeof($filtered_posts)) { $filtered_posts = $matched_products; } else { $filtered_posts = array_intersect($filtered_posts, $matched_products); } $filtered_posts[] = 0; } return (array) $filtered_posts; }
/** * Get line item args for paypal request. * @param WC_Order $order * @return array */ protected function get_line_item_args($order) { /** * Try passing a line item per product if supported. */ if ((!wc_tax_enabled() || !wc_prices_include_tax()) && $this->prepare_line_items($order)) { $line_item_args = array(); $line_item_args['tax_cart'] = $this->number_format($order->get_total_tax(), $order); if ($order->get_total_discount() > 0) { $line_item_args['discount_amount_cart'] = $this->number_format($this->round($order->get_total_discount(), $order), $order); } // Add shipping costs. Paypal ignores anything over 5 digits (999.99 is the max). // We also check that shipping is not the **only** cost as PayPal won't allow payment // if the items have no cost. if ($order->get_shipping_total() > 0 && $order->get_shipping_total() < 999.99 && $this->number_format($order->get_shipping_total() + $order->get_shipping_tax(), $order) !== $this->number_format($order->get_total(), $order)) { $line_item_args['shipping_1'] = $this->number_format($order->get_shipping_total(), $order); } elseif ($order->get_shipping_total() > 0) { $this->add_line_item(sprintf(__('Shipping via %s', 'woocommerce'), $order->get_shipping_method()), 1, $this->number_format($order->get_shipping_total(), $order)); } $line_item_args = array_merge($line_item_args, $this->get_line_items()); /** * Send order as a single item. * * For shipping, we longer use shipping_1 because paypal ignores it if *any* shipping rules are within paypal, and paypal ignores anything over 5 digits (999.99 is the max). */ } else { $this->delete_line_items(); $line_item_args = array(); $all_items_name = $this->get_order_item_names($order); $this->add_line_item($all_items_name ? $all_items_name : __('Order', 'woocommerce'), 1, $this->number_format($order->get_total() - $this->round($order->get_shipping_total() + $order->get_shipping_tax(), $order), $order), $order->get_order_number()); // Add shipping costs. Paypal ignores anything over 5 digits (999.99 is the max). // We also check that shipping is not the **only** cost as PayPal won't allow payment // if the items have no cost. if ($order->get_shipping_total() > 0 && $order->get_shipping_total() < 999.99 && $this->number_format($order->get_shipping_total() + $order->get_shipping_tax(), $order) !== $this->number_format($order->get_total(), $order)) { $line_item_args['shipping_1'] = $this->number_format($order->get_shipping_total() + $order->get_shipping_tax(), $order); } elseif ($order->get_shipping_total() > 0) { $this->add_line_item(sprintf(__('Shipping via %s', 'woocommerce'), $order->get_shipping_method()), 1, $this->number_format($order->get_shipping_total() + $order->get_shipping_tax(), $order)); } $line_item_args = array_merge($line_item_args, $this->get_line_items()); } return $line_item_args; }
/** * Output widget. * * @see WP_Widget * * @param array $args * @param array $instance */ public function widget($args, $instance) { global $wp, $wp_the_query; if (!is_post_type_archive('product') && !is_tax(get_object_taxonomies('product'))) { return; } if (!$wp_the_query->post_count) { return; } $min_price = isset($_GET['min_price']) ? esc_attr($_GET['min_price']) : ''; $max_price = isset($_GET['max_price']) ? esc_attr($_GET['max_price']) : ''; wp_enqueue_script('wc-price-slider'); // Remember current filters/search $fields = ''; if (get_search_query()) { $fields .= '<input type="hidden" name="s" value="' . get_search_query() . '" />'; } if (!empty($_GET['post_type'])) { $fields .= '<input type="hidden" name="post_type" value="' . esc_attr($_GET['post_type']) . '" />'; } if (!empty($_GET['product_cat'])) { $fields .= '<input type="hidden" name="product_cat" value="' . esc_attr($_GET['product_cat']) . '" />'; } if (!empty($_GET['product_tag'])) { $fields .= '<input type="hidden" name="product_tag" value="' . esc_attr($_GET['product_tag']) . '" />'; } if (!empty($_GET['orderby'])) { $fields .= '<input type="hidden" name="orderby" value="' . esc_attr($_GET['orderby']) . '" />'; } if (!empty($_GET['min_rating'])) { $fields .= '<input type="hidden" name="min_rating" value="' . esc_attr($_GET['min_rating']) . '" />'; } if ($_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes()) { foreach ($_chosen_attributes as $attribute => $data) { $taxonomy_filter = 'filter_' . str_replace('pa_', '', $attribute); $fields .= '<input type="hidden" name="' . esc_attr($taxonomy_filter) . '" value="' . esc_attr(implode(',', $data['terms'])) . '" />'; if ('or' == $data['query_type']) { $fields .= '<input type="hidden" name="' . esc_attr(str_replace('pa_', 'query_type_', $attribute)) . '" value="or" />'; } } } // Find min and max price in current result set $prices = $this->get_filtered_price(); $min = floor($prices->min_price); $max = ceil($prices->max_price); if ($min === $max) { return; } $this->widget_start($args, $instance); if ('' == get_option('permalink_structure')) { $form_action = remove_query_arg(array('page', 'paged'), add_query_arg($wp->query_string, '', home_url($wp->request))); } else { $form_action = preg_replace('%\\/page/[0-9]+%', '', home_url(trailingslashit($wp->request))); } // Adjust min and max if the store taxes are not displayed how they are stored if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); foreach ($tax_classes as $tax_class) { $tax_rates = WC_Tax::get_rates($tax_class); $class_min = $min + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($min, $tax_rates)); $class_max = $max + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($max, $tax_rates)); if ($class_min < $min) { $min = $class_min; } if ($class_max > $max) { $max = $class_max; } } } echo '<form method="get" action="' . esc_url($form_action) . '"> <div class="price_slider_wrapper"> <div class="price_slider" style="display:none;"></div> <div class="price_slider_amount"> <input type="text" id="min_price" name="min_price" value="' . esc_attr($min_price) . '" data-min="' . esc_attr(apply_filters('woocommerce_price_filter_widget_min_amount', $min)) . '" placeholder="' . esc_attr__('Min price', 'woocommerce') . '" /> <input type="text" id="max_price" name="max_price" value="' . esc_attr($max_price) . '" data-max="' . esc_attr(apply_filters('woocommerce_price_filter_widget_max_amount', $max)) . '" placeholder="' . esc_attr__('Max price', 'woocommerce') . '" /> <button type="submit" class="button">' . __('Filter', 'woocommerce') . '</button> <div class="price_label" style="display:none;"> ' . __('Price:', 'woocommerce') . ' <span class="from"></span> — <span class="to"></span> </div> ' . $fields . ' <div class="clear"></div> </div> </div> </form>'; $this->widget_end($args); }
/** * Auto-load in-accessible properties on demand. * * @param mixed $key * @return mixed */ public function __get($key) { switch ($key) { case 'prices_include_tax': return wc_prices_include_tax(); break; case 'round_at_subtotal': return 'yes' === get_option('woocommerce_tax_round_at_subtotal'); break; case 'tax_display_cart': return get_option('woocommerce_tax_display_cart'); break; case 'dp': return wc_get_price_decimals(); break; case 'display_totals_ex_tax': case 'display_cart_ex_tax': return $this->tax_display_cart === 'excl'; break; case 'cart_contents_weight': return $this->get_cart_contents_weight(); break; case 'cart_contents_count': return $this->get_cart_contents_count(); break; case 'tax': _deprecated_argument('WC_Cart->tax', '2.3', 'Use WC_Tax:: directly'); $this->tax = new WC_Tax(); return $this->tax; case 'discount_total': _deprecated_argument('WC_Cart->discount_total', '2.3', 'After tax coupons are no longer supported. For more information see: https://woocommerce.wordpress.com/2014/12/upcoming-coupon-changes-in-woocommerce-2-3/'); return 0; } }
/** * Get discount amount for a cart item. * * @param float $discounting_amount Amount the coupon is being applied to * @param array|null $cart_item Cart item being discounted if applicable * @param boolean $single True if discounting a single qty item, false if its the line * @return float Amount this coupon has discounted */ public function get_discount_amount($discounting_amount, $cart_item = null, $single = false) { $discount = 0; $cart_item_qty = is_null($cart_item) ? 1 : $cart_item['quantity']; if ($this->is_type(array('percent_product', 'percent'))) { $discount = $this->coupon_amount * ($discounting_amount / 100); } elseif ($this->is_type('fixed_cart') && !is_null($cart_item) && WC()->cart->subtotal_ex_tax) { /** * This is the most complex discount - we need to divide the discount between rows based on their price in. * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows. * with no price (free) don't get discounted. * * Get item discount by dividing item cost by subtotal to get a %. * * Uses price inc tax if prices include tax to work around https://github.com/woothemes/woocommerce/issues/7669 and https://github.com/woothemes/woocommerce/issues/8074. */ if (wc_prices_include_tax()) { $discount_percent = $cart_item['data']->get_price_including_tax() * $cart_item_qty / WC()->cart->subtotal; } else { $discount_percent = $cart_item['data']->get_price_excluding_tax() * $cart_item_qty / WC()->cart->subtotal_ex_tax; } $discount = $this->coupon_amount * $discount_percent / $cart_item_qty; } elseif ($this->is_type('fixed_product')) { $discount = min($this->coupon_amount, $discounting_amount); $discount = $single ? $discount : $discount * $cart_item_qty; } $discount = min($discount, $discounting_amount); // Handle the limit_usage_to_x_items option if ($this->is_type(array('percent_product', 'fixed_product'))) { if ($discounting_amount) { if ('' === $this->limit_usage_to_x_items) { $limit_usage_qty = $cart_item_qty; } else { $limit_usage_qty = min($this->limit_usage_to_x_items, $cart_item_qty); $this->limit_usage_to_x_items = max(0, $this->limit_usage_to_x_items - $limit_usage_qty); } if ($single) { $discount = $discount * $limit_usage_qty / $cart_item_qty; } else { $discount = $discount / $cart_item_qty * $limit_usage_qty; } } } $discount = round($discount, WC_ROUNDING_PRECISION); return apply_filters('woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this); }
/** * Get the site index. * * This endpoint describes the capabilities of the site. * * @since 2.3 * @return array Index entity */ public function get_index() { // General site data $available = array('store' => array('name' => get_option('blogname'), 'description' => get_option('blogdescription'), 'URL' => get_option('siteurl'), 'wc_version' => WC()->version, 'routes' => array(), 'meta' => array('timezone' => wc_timezone_string(), 'currency' => get_woocommerce_currency(), 'currency_format' => get_woocommerce_currency_symbol(), 'currency_position' => get_option('woocommerce_currency_pos'), 'thousand_separator' => get_option('woocommerce_price_decimal_sep'), 'decimal_separator' => get_option('woocommerce_price_thousand_sep'), 'price_num_decimals' => wc_get_price_decimals(), 'tax_included' => wc_prices_include_tax(), 'weight_unit' => get_option('woocommerce_weight_unit'), 'dimension_unit' => get_option('woocommerce_dimension_unit'), 'ssl_enabled' => 'yes' === get_option('woocommerce_force_ssl_checkout'), 'permalinks_enabled' => '' !== get_option('permalink_structure'), 'links' => array('help' => 'http://woothemes.github.io/woocommerce-rest-api-docs/')))); // Find the available routes foreach ($this->get_routes() as $route => $callbacks) { $data = array(); $route = preg_replace('#\\(\\?P(<\\w+?>).*?\\)#', '$1', $route); foreach (self::$method_map as $name => $bitmask) { foreach ($callbacks as $callback) { // Skip to the next route if any callback is hidden if ($callback[1] & self::HIDDEN_ENDPOINT) { continue 3; } if ($callback[1] & $bitmask) { $data['supports'][] = $name; } if ($callback[1] & self::ACCEPT_DATA) { $data['accepts_data'] = true; } // For non-variable routes, generate links if (strpos($route, '<') === false) { $data['meta'] = array('self' => get_woocommerce_api_url($route)); } } } $available['store']['routes'][$route] = apply_filters('woocommerce_api_endpoints_description', $data); } return apply_filters('woocommerce_api_index', $available); }
/** * Return a meta query for filtering by price. * @return array */ private function price_filter_meta_query() { if (isset($_GET['max_price']) || isset($_GET['min_price'])) { $min = isset($_GET['min_price']) ? floatval($_GET['min_price']) : 0; $max = isset($_GET['max_price']) ? floatval($_GET['max_price']) : 9999999999.0; // If displaying prices in the shop including taxes, but prices don't include taxes.. if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); foreach ($tax_classes as $tax_class) { $tax_rates = WC_Tax::get_rates($tax_class); $class_min = $min - WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($min, $tax_rates)); $class_max = $max - WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($max, $tax_rates)); if ($class_min < $min) { $min = $class_min; } if ($class_max > $max) { $max = $class_max; } } } return array('key' => '_price', 'value' => array($min, $max), 'compare' => 'BETWEEN', 'type' => 'DECIMAL', 'price_filter' => true); } return array(); }
function wc_update_230_options() { // _money_spent and _order_count may be out of sync - clear them delete_metadata('user', 0, '_money_spent', '', true); delete_metadata('user', 0, '_order_count', '', true); // To prevent taxes being hidden when using a default 'no address' in a store with tax inc prices, set the woocommerce_default_customer_address to use the store base address by default if ('' === get_option('woocommerce_default_customer_address', false) && wc_prices_include_tax()) { update_option('woocommerce_default_customer_address', 'base'); } }
/** * Restore renewal flag when cart is reset and modify Product object with renewal order related info * * @since 2.0 */ public function get_cart_item_from_session($cart_item_session_data, $cart_item, $key) { if (isset($cart_item[$this->cart_item_key]['subscription_id'])) { $cart_item_session_data[$this->cart_item_key] = $cart_item[$this->cart_item_key]; $_product = $cart_item_session_data['data']; // Need to get the original subscription price, not the current price $subscription = wcs_get_subscription($cart_item[$this->cart_item_key]['subscription_id']); if ($subscription) { $subscription_items = $subscription->get_items(); $item_to_renew = $subscription_items[$cart_item_session_data[$this->cart_item_key]['subscription_line_item_id']]; $price = $item_to_renew['line_subtotal']; if (wc_prices_include_tax()) { $base_tax_rates = WC_Tax::get_base_tax_rates($_product->tax_class); $base_taxes_on_item = WC_Tax::calc_tax($price, $base_tax_rates, false, false); $price += array_sum($base_taxes_on_item); } $_product->price = $price / $item_to_renew['qty']; // Don't carry over any sign up fee $_product->subscription_sign_up_fee = 0; $_product->post->post_title = apply_filters('woocommerce_subscriptions_renewal_product_title', $_product->get_title(), $_product); // Make sure the same quantity is renewed $cart_item_session_data['quantity'] = $item_to_renew['qty']; } } return $cart_item_session_data; }
/** * widget function. * * @see WP_Widget * * @param array $args * @param array $instance */ public function widget($args, $instance) { global $_chosen_attributes, $wpdb, $wp; if (!is_post_type_archive('product') && !is_tax(get_object_taxonomies('product'))) { return; } if (sizeof(WC()->query->unfiltered_product_ids) == 0) { return; // None shown - return } $min_price = isset($_GET['min_price']) ? esc_attr($_GET['min_price']) : ''; $max_price = isset($_GET['max_price']) ? esc_attr($_GET['max_price']) : ''; wp_enqueue_script('wc-price-slider'); // Remember current filters/search $fields = ''; if (get_search_query()) { $fields .= '<input type="hidden" name="s" value="' . get_search_query() . '" />'; } if (!empty($_GET['post_type'])) { $fields .= '<input type="hidden" name="post_type" value="' . esc_attr($_GET['post_type']) . '" />'; } if (!empty($_GET['product_cat'])) { $fields .= '<input type="hidden" name="product_cat" value="' . esc_attr($_GET['product_cat']) . '" />'; } if (!empty($_GET['product_tag'])) { $fields .= '<input type="hidden" name="product_tag" value="' . esc_attr($_GET['product_tag']) . '" />'; } if (!empty($_GET['orderby'])) { $fields .= '<input type="hidden" name="orderby" value="' . esc_attr($_GET['orderby']) . '" />'; } if ($_chosen_attributes) { foreach ($_chosen_attributes as $attribute => $data) { $taxonomy_filter = 'filter_' . str_replace('pa_', '', $attribute); $fields .= '<input type="hidden" name="' . esc_attr($taxonomy_filter) . '" value="' . esc_attr(implode(',', $data['terms'])) . '" />'; if ('or' == $data['query_type']) { $fields .= '<input type="hidden" name="' . esc_attr(str_replace('pa_', 'query_type_', $attribute)) . '" value="or" />'; } } } if (0 === sizeof(WC()->query->layered_nav_product_ids)) { $min = floor($wpdb->get_var("\n\t\t\t\tSELECT min(meta_value + 0)\n\t\t\t\tFROM {$wpdb->posts} as posts\n\t\t\t\tLEFT JOIN {$wpdb->postmeta} as postmeta ON posts.ID = postmeta.post_id\n\t\t\t\tWHERE meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price', '_min_variation_price')))) . "')\n\t\t\t\tAND meta_value != ''\n\t\t\t")); $max = ceil($wpdb->get_var("\n\t\t\t\tSELECT max(meta_value + 0)\n\t\t\t\tFROM {$wpdb->posts} as posts\n\t\t\t\tLEFT JOIN {$wpdb->postmeta} as postmeta ON posts.ID = postmeta.post_id\n\t\t\t\tWHERE meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price')))) . "')\n\t\t\t")); } else { $min = floor($wpdb->get_var("\n\t\t\t\tSELECT min(meta_value + 0)\n\t\t\t\tFROM {$wpdb->posts} as posts\n\t\t\t\tLEFT JOIN {$wpdb->postmeta} as postmeta ON posts.ID = postmeta.post_id\n\t\t\t\tWHERE meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price', '_min_variation_price')))) . "')\n\t\t\t\tAND meta_value != ''\n\t\t\t\tAND (\n\t\t\t\t\tposts.ID IN (" . implode(',', array_map('absint', WC()->query->layered_nav_product_ids)) . ")\n\t\t\t\t\tOR (\n\t\t\t\t\t\tposts.post_parent IN (" . implode(',', array_map('absint', WC()->query->layered_nav_product_ids)) . ")\n\t\t\t\t\t\tAND posts.post_parent != 0\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t")); $max = ceil($wpdb->get_var("\n\t\t\t\tSELECT max(meta_value + 0)\n\t\t\t\tFROM {$wpdb->posts} as posts\n\t\t\t\tLEFT JOIN {$wpdb->postmeta} as postmeta ON posts.ID = postmeta.post_id\n\t\t\t\tWHERE meta_key IN ('" . implode("','", array_map('esc_sql', apply_filters('woocommerce_price_filter_meta_keys', array('_price')))) . "')\n\t\t\t\tAND (\n\t\t\t\t\tposts.ID IN (" . implode(',', array_map('absint', WC()->query->layered_nav_product_ids)) . ")\n\t\t\t\t\tOR (\n\t\t\t\t\t\tposts.post_parent IN (" . implode(',', array_map('absint', WC()->query->layered_nav_product_ids)) . ")\n\t\t\t\t\t\tAND posts.post_parent != 0\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t")); } if ($min == $max) { return; } $this->widget_start($args, $instance); if ('' == get_option('permalink_structure')) { $form_action = remove_query_arg(array('page', 'paged'), add_query_arg($wp->query_string, '', home_url($wp->request))); } else { $form_action = preg_replace('%\\/page/[0-9]+%', '', home_url(trailingslashit($wp->request))); } if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $min = 0; foreach ($tax_classes as $tax_class) { $tax_rates = WC_Tax::get_rates($tax_class); $class_min = $min + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($min, $tax_rates)); $class_max = $max + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($max, $tax_rates)); if ($min === 0 || $class_min < $min) { $min = $class_min; } if ($class_max > $max) { $max = $class_max; } } } echo '<form method="get" action="' . esc_url($form_action) . '"> <div class="price_slider_wrapper"> <div class="price_slider" style="display:none;"></div> <div class="price_slider_amount"> <input type="text" id="min_price" name="min_price" value="' . esc_attr($min_price) . '" data-min="' . esc_attr(apply_filters('woocommerce_price_filter_widget_min_amount', $min)) . '" placeholder="' . esc_attr__('Min price', 'woocommerce') . '" /> <input type="text" id="max_price" name="max_price" value="' . esc_attr($max_price) . '" data-max="' . esc_attr(apply_filters('woocommerce_price_filter_widget_max_amount', $max)) . '" placeholder="' . esc_attr__('Max price', 'woocommerce') . '" /> <button type="submit" class=" filter">' . __('Filter', 'woocommerce') . '</button> <div class="price_label price-input" style="display:none;"> ' . __('Price:', 'woocommerce') . ' <span class="from"></span> — <span class="to"></span> </div> ' . $fields . ' <div class="clear"></div> </div> </div> </form>'; $this->widget_end($args); }
<?php /** * Update WC to 2.3.0 * * @author WooThemes * @category Admin * @package WooCommerce/Admin/Updates * @version 2.3.0 */ if (!defined('ABSPATH')) { exit; } // _money_spent and _order_count may be out of sync - clear them delete_metadata('user', 0, '_money_spent', '', true); delete_metadata('user', 0, '_order_count', '', true); // To prevent taxes being hidden when using a default 'no address' in a store with tax inc prices, set the woocommerce_default_customer_address to use the store base address by default if ('' === get_option('woocommerce_default_customer_address', false) && wc_prices_include_tax()) { update_option('woocommerce_default_customer_address', 'base'); }
/** * Calculates a price (could be per period price or sign-up fee) for a subscription less tax * if the subscription is taxable and the prices in the store include tax. * * Based on the WC_Product::get_price_excluding_tax() function. * * @param float $price The price to adjust based on taxes * @param WC_Product $product The product the price belongs too (needed to determine tax class) * @since 1.0 */ public static function calculate_tax_for_subscription($price, $product, $deduct_base_taxes = false) { _deprecated_function(__METHOD__, '1.5.8', 'WC_Product::get_price_including_tax()'); if ($product->is_taxable()) { $tax = new WC_Tax(); $base_tax_rates = $tax->get_shop_base_rate($product->tax_class); $tax_rates = $tax->get_rates($product->get_tax_class()); // This will get the base rate unless we're on the checkout page if ($deduct_base_taxes && wc_prices_include_tax()) { $base_taxes = $tax->calc_tax($price, $base_tax_rates, true); $taxes = $tax->calc_tax($price - array_sum($base_taxes), $tax_rates, false); } elseif (get_option('woocommerce_prices_include_tax') == 'yes') { $taxes = $tax->calc_tax($price, $base_tax_rates, true); } else { $taxes = $tax->calc_tax($price, $base_tax_rates, false); } $tax_amount = $tax->get_tax_total($taxes); } else { $tax_amount = 0; } return $tax_amount; }
/** * Get the customer tax location based on their status and the current page. * * Used by get_rates(), get_shipping_rates(). * * @param $tax_class string Optional, passed to the filter for advanced tax setups. * @return array */ public static function get_tax_location($tax_class = '') { $location = array(); if (!empty(WC()->customer)) { $location = WC()->customer->get_taxable_address(); } elseif (wc_prices_include_tax() || 'base' === get_option('woocommerce_default_customer_address') || 'base' === get_option('woocommerce_tax_based_on')) { $location = array(WC()->countries->get_base_country(), WC()->countries->get_base_state(), WC()->countries->get_base_postcode(), WC()->countries->get_base_city()); } return apply_filters('woocommerce_get_tax_location', $location, $tax_class); }
/** * Get Price Range for given product ids. * If filtered is true then return price range for filtered products, * otherwise return price range for all products. * * @param boolean $filtered * @return array */ public function getPriceRange($filtered = true) { if ($filtered === true) { $price_range = $this->filteredProductsPriceRange(); } else { $price_range = $this->unfilteredProductsPriceRange(); } if (sizeof($price_range) > 2) { $min = $max = false; foreach ($price_range as $price) { if ($min === false || $min > (int) $price) { $min = floor($price); } if ($max === false || $max < (int) $price) { $max = ceil($price); } } // if tax enabled and shop page shows price including tax if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); foreach ($tax_classes as $tax_class) { $tax_rates = WC_Tax::get_rates($tax_class); $class_min = $min + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($min, $tax_rates)); $class_max = $max + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($max, $tax_rates)); $min = $max = false; if ($min === false || $min > (int) $class_min) { $min = floor($class_min); } if ($max === false || $max < (int) $class_max) { $max = ceil($class_max); } } } // if WooCommerce Currency Switcher plugin is activated if (class_exists('WOOCS')) { $woocs = new WOOCS(); $chosen_currency = $woocs->get_woocommerce_currency(); $currencies = $woocs->get_currencies(); if (sizeof($currencies) > 0) { foreach ($currencies as $currency) { if ($currency['name'] == $chosen_currency) { $rate = $currency['rate']; } } $min = floor($min * $rate); $max = ceil($max * $rate); } } if ($min == $max) { // empty array return array(); } else { // array with min and max values return array($min, $max); } } else { // empty array return array(); } }
/** * Output widget. * * @see WP_Widget * * @param array $args * @param array $instance */ public function widget($args, $instance) { global $wp, $wp_the_query; if (!is_post_type_archive('product') && !is_tax(get_object_taxonomies('product'))) { return; } if (!$wp_the_query->post_count) { return; } // Remember current filters/search if ('' == get_option('permalink_structure')) { $link_url = remove_query_arg(array('page', 'paged'), add_query_arg($wp->query_string, '', home_url($wp->request))); } else { $link_url = preg_replace('%\\/page/[0-9]+%', '', home_url(trailingslashit($wp->request))); } if (get_search_query()) { $link_url = add_query_arg('s', get_search_query(), $link_url); } if (!empty($_GET['post_type'])) { $link_url = add_query_arg('post_type', urlencode($_GET['post_type']), $link_url); } if (!empty($_GET['product_cat'])) { $link_url = add_query_arg('product_cat', urlencode($_GET['product_cat']), $link_url); } if (!empty($_GET['product_tag'])) { $link_url = add_query_arg('product_tag', urlencode($_GET['product_tag']), $link_url); } if (!empty($_GET['orderby'])) { $link_url = add_query_arg('orderby', urlencode($_GET['orderby']), $link_url); } if ($_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes()) { foreach ($_chosen_attributes as $attribute => $data) { $taxonomy_filter = 'filter_' . str_replace('pa_', '', $attribute); $link_url = add_query_arg($taxonomy_filter, urlencode(implode(',', $data['terms'])), $link_url); if ('or' == $data['query_type']) { $link_url = add_query_arg(str_replace('pa_', 'query_type_', $attribute), 'or', $link_url); } } } // Find min and max price in current result set $prices = $this->get_filtered_price(); $min = floor($prices->min_price); $max = ceil($prices->max_price); if ($min === $max) { return; } $this->widget_start($args, $instance); /** * Adjust max if the store taxes are not displayed how they are stored. * Min is left alone because the product may not be taxable. * Kicks in when prices excluding tax are displayed including tax. */ if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $class_max = $max; foreach ($tax_classes as $tax_class) { if ($tax_rates = WC_Tax::get_rates($tax_class)) { $class_max = $max + WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($max, $tax_rates)); } } $max = $class_max; } $minprice = isset($_GET['min_price']) ? esc_attr($_GET['min_price']) : ''; $maxprice = isset($_GET['max_price']) ? esc_attr($_GET['max_price']) : ''; $output = ''; $min_price = 0; $range_size = intval($instance['range_size']); $max_ranges = intval($instance['max_ranges']) - 1; $count = 0; if (strlen($minprice) > 0) { $output .= '<li><a href="' . esc_url($link_url) . '">' . esc_html__('All', 'cruxstore') . '</a></li>'; } else { $output .= '<li class="selected">' . esc_html__('All', 'cruxstore') . '</li>'; } while ($count <= $max_ranges) { $step = $min_price; $min_price += $range_size; if ($count != $max_ranges) { if ($min_price > $max) { $min_price = $max; } $link = add_query_arg(array('min_price' => $step, 'max_price' => $min_price), $link_url); $price_text = wc_price($step) . ' - ' . wc_price($min_price); } else { $link = add_query_arg(array('min_price' => $step, 'max_price' => $max), $link_url); $price_text = wc_price($step) . '+'; } if ($step == $minprice && $min_price == $maxprice) { $output .= '<li class="selected">' . $price_text . '</li>'; } else { $output .= '<li><a href="' . esc_url($link) . '">' . $price_text . '</a></li>'; } $count++; if ($min_price == $max) { break; } } printf('<ul>%s</ul>', $output); $this->widget_end($args); }
/** * Get line item args for paypal request * @param WC_Order $order * @return array */ protected function get_line_item_args($order) { /** * Try passing a line item per product if supported */ if ((!wc_tax_enabled() || !wc_prices_include_tax()) && $this->prepare_line_items($order)) { $line_item_args = $this->get_line_items(); $line_item_args['tax_cart'] = $this->number_format($order->get_total_tax(), $order); if ($order->get_total_discount() > 0) { $line_item_args['discount_amount_cart'] = $this->round($order->get_total_discount(), $order); } /** * Send order as a single item * * For shipping, we longer use shipping_1 because paypal ignores it if *any* shipping rules are within paypal, and paypal ignores anything over 5 digits (999.99 is the max) */ } else { $this->delete_line_items(); $all_items_name = $this->get_order_item_names($order); $this->add_line_item($all_items_name ? $all_items_name : __('Order', 'woocommerce'), 1, $this->number_format($order->get_total() - $this->round($order->get_total_shipping() + $order->get_shipping_tax(), $order), $order), $order->get_order_number()); $this->add_line_item(sprintf(__('Shipping via %s', 'woocommerce'), ucwords($order->get_shipping_method())), 1, $this->number_format($order->get_total_shipping() + $order->get_shipping_tax(), $order)); $line_item_args = $this->get_line_items(); } return $line_item_args; }
/** * For a given product, and optionally price/qty, work out the price with tax excluded, based on store settings. * @since 2.7.0 * @param WC_Product $product * @param array $args * @return float */ function wc_get_price_excluding_tax($product, $args = array()) { $args = wp_parse_args($args, array('qty' => '', 'price' => '')); $price = $args['price'] ? $args['price'] : $product->get_price(); $qty = $args['qty'] ? $args['qty'] : 1; if ($product->is_taxable() && wc_prices_include_tax()) { $tax_rates = WC_Tax::get_base_tax_rates($product->get_tax_class(true)); $taxes = WC_Tax::calc_tax($price * $qty, $tax_rates, true); $price = WC_Tax::round($price * $qty - array_sum($taxes)); } else { $price = $price * $qty; } return apply_filters('woocommerce_get_price_excluding_tax', $price, $qty, $product); }
public function get_line_item_args($order) { /** * Try passing a line item per product if supported */ if ((!wc_tax_enabled() || !wc_prices_include_tax()) && $this->prepare_line_items($order)) { $line_item_args = $this->get_line_items(); $line_item_args['tax_cart'] = $order->get_total_tax(); if ($order->get_total_discount() > 0) { $line_item_args['discount_amount_cart'] = round($order->get_total_discount(), 2); } /** * Send order as a single item * * For shipping, we longer use shipping_1 because paypal ignores it if *any* shipping rules are within paypal, and paypal ignores anything over 5 digits (999.99 is the max) */ } return $line_item_args; }
/** * Test wc_prices_include_tax(). * * @since 2.3.0 */ public function test_wc_prices_include_tax() { $this->assertEquals(false, wc_prices_include_tax()); }
/** * Return a meta query for filtering by price. * @return array */ private function price_filter_meta_query() { if (isset($_GET['max_price']) || isset($_GET['min_price'])) { $min = isset($_GET['min_price']) ? floatval($_GET['min_price']) : 0; $max = isset($_GET['max_price']) ? floatval($_GET['max_price']) : 9999999999.0; /** * Adjust if the store taxes are not displayed how they are stored. * Max is left alone because the filter was already increased. * Kicks in when prices excluding tax are displayed including tax. */ if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) { $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $class_min = $min; foreach ($tax_classes as $tax_class) { if ($tax_rates = WC_Tax::get_rates($tax_class)) { $class_min = $min - WC_Tax::get_tax_total(WC_Tax::calc_exclusive_tax($min, $tax_rates)); } } $min = $class_min; } return array('key' => '_price', 'value' => array($min, $max), 'compare' => 'BETWEEN', 'type' => 'DECIMAL', 'price_filter' => true); } return array(); }
/** * PayPal cannot properly calculate order totals when prices include tax (due * to rounding issues), so line items are skipped and the order is sent as * a single item * * @since 2.0.9 * @param WC_Order $order Optional. The WC_Order object. Default null. * @return bool true if line items should be skipped, false otherwise */ private function skip_line_items($order = null) { if (isset($order->prices_include_tax)) { $skip_line_items = $order->prices_include_tax; } else { $skip_line_items = wc_prices_include_tax(); } /** * Filter whether line items should be skipped or not * * @since 3.3.0 * @param bool $skip_line_items True if line items should be skipped, false otherwise * @param WC_Order/null $order The WC_Order object or null. */ return apply_filters('wcs_paypal_reference_transaction_skip_line_items', $skip_line_items, $order); }