/** * 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); }
/** * Set tax class. * * @param string $value * @throws WC_Data_Exception */ public function set_tax_class($value) { if ($value && !in_array($value, WC_Tax::get_tax_classes())) { $this->error('order_item_fee_invalid_tax_class', __('Invalid tax class', 'woocommerce')); } $this->set_prop('tax_class', $value); }
function ywev_get_tax_classes() { if (version_compare(WOOCOMMERCE_VERSION, '2.3', '<')) { return array_filter(array_map('trim', explode("\n", get_option('woocommerce_tax_classes')))); } else { return WC_Tax::get_tax_classes(); } }
public function tax_classes() { $tax_classes = WC_Tax::get_tax_classes(); $classes_options = array(); if (!empty($tax_classes)) { foreach ($tax_classes as $class) { $classes_options[sanitize_title($class)] = esc_html($class); } } return $classes_options; }
/** * Returns all tax classes, class => label * @return array */ public static function tax_classes() { $classes = array('' => __('Standard', 'woocommerce')); // get_tax_classes method introduced in WC 2.3 if (method_exists('WC_Tax', 'get_tax_classes')) { $labels = WC_Tax::get_tax_classes(); } else { $labels = array_filter(array_map('trim', explode("\n", get_option('woocommerce_tax_classes')))); } foreach ($labels as $label) { $classes[sanitize_title($label)] = $label; } return $classes; }
/** * 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 the query params for collections of attachments. * * @return array */ public function get_collection_params() { $params = parent::get_collection_params(); $params['slug'] = array('description' => __('Limit result set to products with a specific slug.', 'woocommerce'), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg'); $params['status'] = array('default' => 'any', 'description' => __('Limit result set to products assigned a specific status.', 'woocommerce'), 'type' => 'string', 'enum' => array_merge(array('any'), array_keys(get_post_statuses())), 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg'); $params['type'] = array('description' => __('Limit result set to products assigned a specific type.', 'woocommerce'), 'type' => 'string', 'enum' => array_keys(wc_get_product_types()), 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg'); $params['sku'] = array('description' => __('Limit result set to products with a specific SKU.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg'); $params['featured'] = array('description' => __('Limit result set to featured products.', 'woocommerce'), 'type' => 'boolean', 'sanitize_callback' => 'wc_string_to_bool', 'validate_callback' => 'rest_validate_request_arg'); $params['category'] = array('description' => __('Limit result set to products assigned a specific category ID.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg'); $params['tag'] = array('description' => __('Limit result set to products assigned a specific tag ID.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg'); $params['shipping_class'] = array('description' => __('Limit result set to products assigned a specific shipping class ID.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg'); $params['attribute'] = array('description' => __('Limit result set to products with a specific attribute.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg'); $params['attribute_term'] = array('description' => __('Limit result set to products with a specific attribute term ID (required an assigned attribute).', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg'); if (wc_tax_enabled()) { $params['tax_class'] = array('description' => __('Limit result set to products with a specific tax class.', 'woocommerce'), 'type' => 'string', 'enum' => array_map('sanitize_title', array_merge(array('standard'), WC_Tax::get_tax_classes())), 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg'); } $params['in_stock'] = array('description' => __('Limit result set to products in stock or out of stock.', 'woocommerce'), 'type' => 'boolean', 'sanitize_callback' => 'wc_string_to_bool', 'validate_callback' => 'rest_validate_request_arg'); $params['on_sale'] = array('description' => __('Limit result set to products on sale.', 'woocommerce'), 'type' => 'boolean', 'sanitize_callback' => 'wc_string_to_bool', 'validate_callback' => 'rest_validate_request_arg'); $params['min_price'] = array('description' => __('Limit result set to products based on a minimum price.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg'); $params['max_price'] = array('description' => __('Limit result set to products based on a maximum price.', 'woocommerce'), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg'); return $params; }
/** * Get product tax class options. * * @since 2.7.0 * @return array */ function wc_get_product_tax_class_options() { $tax_classes = WC_Tax::get_tax_classes(); $tax_class_options = array(); $tax_class_options[''] = __('Standard', 'woocommerce'); if (!empty($tax_classes)) { foreach ($tax_classes as $class) { $tax_class_options[sanitize_title($class)] = $class; } } return $tax_class_options; }
/** * add_fees_settings. * * @version 2.3.0 */ function add_fees_settings($settings) { // Gateway's Extra Fees $settings[] = array('title' => __('Payment Gateways Fees and Discounts Options', 'woocommerce-jetpack'), 'type' => 'title', 'desc' => __('This section lets you set extra fees for payment gateways.', 'woocommerce-jetpack'), 'id' => 'wcj_payment_gateways_fees_options'); //$available_gateways = WC()->payment_gateways->payment_gateways(); global $woocommerce; $available_gateways = $woocommerce->payment_gateways->payment_gateways(); //$available_gateways = WC()->payment_gateways(); foreach ($available_gateways as $key => $gateway) { /*echo '<h5>' . $gateway->title . '</h5>'; if ( $gateway->is_available() ) echo '<strong style="color: green;">' . __( 'Available', 'woocommerce-jetpack' ) . '</strong>'; else echo '<strong style="color: red;">' . __( 'Not available', 'woocommerce-jetpack' ) . '</strong>';*/ $settings = array_merge($settings, array(array('title' => $gateway->title, 'desc' => __('Fee (or discount) title to show to customer.', 'woocommerce-jetpack'), 'desc_tip' => __('Leave blank to disable.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_text_' . $key, 'default' => '', 'type' => 'text'), array('title' => '', 'desc' => __('Fee (or discount) type.', 'woocommerce-jetpack'), 'desc_tip' => __('Percent or fixed value.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_type_' . $key, 'default' => 'fixed', 'type' => 'select', 'options' => array('fixed' => __('Fixed', 'woocommerce-jetpack'), 'percent' => __('Percent', 'woocommerce-jetpack'))), array('title' => '', 'desc' => __('Fee (or discount) value.', 'woocommerce-jetpack'), 'desc_tip' => __('The value. For discount enter a negative number.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_value_' . $key, 'default' => 0, 'type' => 'number', 'custom_attributes' => array('step' => '0.01')), array('title' => '', 'desc' => __('Minimum cart amount for adding the fee (or discount).', 'woocommerce-jetpack'), 'desc_tip' => __('Set 0 to disable.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_min_cart_amount_' . $key, 'default' => 0, 'type' => 'number', 'custom_attributes' => array('step' => '0.01', 'min' => '0')), array('title' => '', 'desc' => __('Maximum cart amount for adding the fee (or discount).', 'woocommerce-jetpack'), 'desc_tip' => __('Set 0 to disable.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_max_cart_amount_' . $key, 'default' => 0, 'type' => 'number', 'custom_attributes' => array('step' => '0.01', 'min' => '0')), array('title' => '', 'desc' => __('Round the fee (or discount) value before adding to the cart.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_round_' . $key, 'default' => 'no', 'type' => 'checkbox'), array('title' => '', 'desc' => __('If rounding is enabled, set precision here.', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_round_precision_' . $key, 'default' => 0, 'type' => 'number', 'custom_attributes' => array('step' => '1', 'min' => '0')), array('title' => '', 'desc' => __('Is taxable?', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_is_taxable_' . $key, 'default' => 'no', 'type' => 'checkbox'), array('title' => '', 'desc' => __('Tax Class (only if Taxable selected).', 'woocommerce-jetpack'), 'id' => 'wcj_gateways_fees_tax_class_id_' . $key, 'default' => '', 'type' => 'select', 'options' => array_merge(array(__('Standard Rate', 'woocommerce-jetpack')), WC_Tax::get_tax_classes())))); } $settings[] = array('type' => 'sectionend', 'id' => 'wcj_payment_gateways_fees_options'); return $settings; }
/** * Show options for the variable product type */ public static function output_variations() { global $post; $attributes = maybe_unserialize(get_post_meta($post->ID, '_product_attributes', true)); // See if any are set $variation_attribute_found = false; if ($attributes) { foreach ($attributes as $attribute) { if (isset($attribute['is_variation'])) { $variation_attribute_found = true; break; } } } // Get tax classes $tax_classes = WC_Tax::get_tax_classes(); $tax_class_options = array(); $tax_class_options[''] = __('Standard', 'woocommerce'); if ($tax_classes) { foreach ($tax_classes as $class) { $tax_class_options[sanitize_title($class)] = esc_attr($class); } } $backorder_options = array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce')); $stock_status_options = array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce')); ?> <div id="variable_product_options" class="panel wc-metaboxes-wrapper"><div id="variable_product_options_inner"> <?php if (!$variation_attribute_found) { ?> <div id="message" class="inline woocommerce-message"> <p><?php _e('Before adding variations, add and save some attributes on the <strong>Attributes</strong> tab.', 'woocommerce'); ?> </p> <p class="submit"><a class="button-primary" href="<?php echo esc_url(apply_filters('woocommerce_docs_url', 'http://docs.woothemes.com/document/variable-product/', 'product-variations')); ?> " target="_blank"><?php _e('Learn more', 'woocommerce'); ?> </a></p> </div> <?php } else { ?> <p class="toolbar"> <a href="#" class="close_all"><?php _e('Close all', 'woocommerce'); ?> </a><a href="#" class="expand_all"><?php _e('Expand all', 'woocommerce'); ?> </a> <select id="field_to_edit"> <option value=""><?php _e('Choose a field to bulk edit…', 'woocommerce'); ?> </option> <optgroup label="<?php esc_attr_e('Status', 'woocommerce'); ?> "> <option value="toggle_enabled"><?php _e('Toggle "Enabled"', 'woocommerce'); ?> </option> <option value="toggle_downloadable"><?php _e('Toggle "Downloadable"', 'woocommerce'); ?> </option> <option value="toggle_virtual"><?php _e('Toggle "Virtual"', 'woocommerce'); ?> </option> <option value="delete_all"><?php _e('Delete all variations', 'woocommerce'); ?> </option> </optgroup> <optgroup label="<?php esc_attr_e('Pricing', 'woocommerce'); ?> "> <option value="variable_regular_price"><?php _e('Prices', 'woocommerce'); ?> </option> <option value="variable_regular_price_increase"><?php _e('Prices increase by (fixed amount or %)', 'woocommerce'); ?> </option> <option value="variable_regular_price_decrease"><?php _e('Prices decrease by (fixed amount or %)', 'woocommerce'); ?> </option> <option value="variable_sale_price"><?php _e('Sale prices', 'woocommerce'); ?> </option> <option value="variable_sale_price_increase"><?php _e('Sale prices increase by (fixed amount or %)', 'woocommerce'); ?> </option> <option value="variable_sale_price_decrease"><?php _e('Sale prices decrease by (fixed amount or %)', 'woocommerce'); ?> </option> <option value="variable_sale_schedule"><?php _e('Scheduled sale dates', 'woocommerce'); ?> </option> </optgroup> <optgroup label="<?php esc_attr_e('Inventory', 'woocommerce'); ?> "> <option value="toggle_manage_stock"><?php _e('Toggle "Manage stock"', 'woocommerce'); ?> </option> <option value="variable_stock"><?php _e('Stock', 'woocommerce'); ?> </option> </optgroup> <optgroup label="<?php esc_attr_e('Shipping', 'woocommerce'); ?> "> <option value="variable_length"><?php _e('Length', 'woocommerce'); ?> </option> <option value="variable_width"><?php _e('Width', 'woocommerce'); ?> </option> <option value="variable_height"><?php _e('Height', 'woocommerce'); ?> </option> <option value="variable_weight"><?php _e('Weight', 'woocommerce'); ?> </option> </optgroup> <optgroup label="<?php esc_attr_e('Downloadable products', 'woocommerce'); ?> "> <option value="variable_download_limit"><?php _e('Download limit', 'woocommerce'); ?> </option> <option value="variable_download_expiry"><?php _e('Download Expiry', 'woocommerce'); ?> </option> </optgroup> <?php do_action('woocommerce_variable_product_bulk_edit_actions'); ?> </select> <a class="button bulk_edit"><?php _e('Go', 'woocommerce'); ?> </a> </p> <div class="woocommerce_variations wc-metaboxes"> <?php // Get parent data $parent_data = array('id' => $post->ID, 'attributes' => $attributes, 'tax_class_options' => $tax_class_options, 'sku' => get_post_meta($post->ID, '_sku', true), 'weight' => wc_format_localized_decimal(get_post_meta($post->ID, '_weight', true)), 'length' => wc_format_localized_decimal(get_post_meta($post->ID, '_length', true)), 'width' => wc_format_localized_decimal(get_post_meta($post->ID, '_width', true)), 'height' => wc_format_localized_decimal(get_post_meta($post->ID, '_height', true)), 'tax_class' => get_post_meta($post->ID, '_tax_class', true), 'backorder_options' => $backorder_options, 'stock_status_options' => $stock_status_options); if (!$parent_data['weight']) { $parent_data['weight'] = wc_format_localized_decimal(0); } if (!$parent_data['length']) { $parent_data['length'] = wc_format_localized_decimal(0); } if (!$parent_data['width']) { $parent_data['width'] = wc_format_localized_decimal(0); } if (!$parent_data['height']) { $parent_data['height'] = wc_format_localized_decimal(0); } // Get variations $args = array('post_type' => 'product_variation', 'post_status' => array('private', 'publish'), 'numberposts' => -1, 'orderby' => 'menu_order', 'order' => 'asc', 'post_parent' => $post->ID); $variations = get_posts($args); $loop = 0; if ($variations) { foreach ($variations as $variation) { $variation_id = absint($variation->ID); $variation_meta = get_post_meta($variation_id); $variation_data = array(); $shipping_classes = get_the_terms($variation_id, 'product_shipping_class'); $variation_fields = array('_sku' => '', '_stock' => '', '_regular_price' => '', '_sale_price' => '', '_weight' => '', '_length' => '', '_width' => '', '_height' => '', '_download_limit' => '', '_download_expiry' => '', '_downloadable_files' => '', '_downloadable' => '', '_virtual' => '', '_thumbnail_id' => '', '_sale_price_dates_from' => '', '_sale_price_dates_to' => '', '_manage_stock' => '', '_stock_status' => '', '_backorders' => null, '_tax_class' => null); foreach ($variation_fields as $field => $value) { $variation_data[$field] = isset($variation_meta[$field][0]) ? maybe_unserialize($variation_meta[$field][0]) : $value; } // Add the variation attributes foreach ($variation_meta as $key => $value) { if (false !== strpos($key, 'attribute_')) { $variation_data[$key] = $value; } } // Formatting $variation_data['_regular_price'] = wc_format_localized_price($variation_data['_regular_price']); $variation_data['_sale_price'] = wc_format_localized_price($variation_data['_sale_price']); $variation_data['_weight'] = wc_format_localized_decimal($variation_data['_weight']); $variation_data['_length'] = wc_format_localized_decimal($variation_data['_length']); $variation_data['_width'] = wc_format_localized_decimal($variation_data['_width']); $variation_data['_height'] = wc_format_localized_decimal($variation_data['_height']); $variation_data['_thumbnail_id'] = absint($variation_data['_thumbnail_id']); $variation_data['image'] = $variation_data['_thumbnail_id'] ? wp_get_attachment_thumb_url($variation_data['_thumbnail_id']) : ''; $variation_data['shipping_class'] = $shipping_classes && !is_wp_error($shipping_classes) ? current($shipping_classes)->term_id : ''; // Stock BW compat if ('' !== $variation_data['_stock']) { $variation_data['_manage_stock'] = 'yes'; } include 'views/html-variation-admin.php'; $loop++; } } ?> </div> <p class="toolbar"> <button type="button" class="button button-primary add_variation" <?php disabled($variation_attribute_found, false); ?> ><?php _e('Add Variation', 'woocommerce'); ?> </button> <button type="button" class="button link_all_variations" <?php disabled($variation_attribute_found, false); ?> ><?php _e('Link all variations', 'woocommerce'); ?> </button> <strong><?php _e('Defaults', 'woocommerce'); ?> : <span class="tips" data-tip="<?php _e('These are the attributes that will be pre-selected on the frontend.', 'woocommerce'); ?> ">[?]</span></strong> <?php $default_attributes = maybe_unserialize(get_post_meta($post->ID, '_default_attributes', true)); foreach ($attributes as $attribute) { // Only deal with attributes that are variations if (!$attribute['is_variation']) { continue; } // Get current value for variation (if set) $variation_selected_value = isset($default_attributes[sanitize_title($attribute['name'])]) ? $default_attributes[sanitize_title($attribute['name'])] : ''; // Name will be something like attribute_pa_color echo '<select name="default_attribute_' . sanitize_title($attribute['name']) . '"><option value="">' . __('No default', 'woocommerce') . ' ' . esc_html(wc_attribute_label($attribute['name'])) . '…</option>'; // Get terms for attribute taxonomy or value if its a custom attribute if ($attribute['is_taxonomy']) { $post_terms = wp_get_post_terms($post->ID, $attribute['name']); foreach ($post_terms as $term) { echo '<option ' . selected($variation_selected_value, $term->slug, false) . ' value="' . esc_attr($term->slug) . '">' . apply_filters('woocommerce_variation_option_name', esc_html($term->name)) . '</option>'; } } else { $options = array_map('trim', explode(WC_DELIMITER, $attribute['value'])); foreach ($options as $option) { echo '<option ' . selected(sanitize_title($variation_selected_value), sanitize_title($option), false) . ' value="' . esc_attr(sanitize_title($option)) . '">' . esc_html(apply_filters('woocommerce_variation_option_name', $option)) . '</option>'; } } echo '</select>'; } ?> </p> <?php } ?> </div></div> <?php }
/** * Get tax class being edited * @return string */ private function get_current_tax_class() { global $current_section; $tax_classes = WC_Tax::get_tax_classes(); $current_class = ''; foreach ($tax_classes as $class) { if (sanitize_title($class) == $current_section) { $current_class = $class; } } return $current_class; }
/** * Test getting the tax classes. */ public function test_get_tax_classes() { $tax_classes = WC_Tax::get_tax_classes(); $this->assertEquals($tax_classes, array('Reduced rate', 'Zero rate')); }
/** * Set tax class. * @param string $value * @throws WC_Data_Exception */ public function set_tax_class($value) { if ($value && !in_array($value, WC_Tax::get_tax_classes())) { $this->error('order_item_product_invalid_tax_class', __('Invalid tax class', 'woocommerce')); } $this->_data['tax_class'] = $value; }
/** * 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(); }
/** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * Will use the base country unless customer addresses are set. * * @return bool success or fail. */ public function calculate_taxes() { $tax_total = 0; $shipping_tax_total = 0; $taxes = array(); $shipping_taxes = array(); $tax_based_on = get_option('woocommerce_tax_based_on'); // If is_vat_exempt is 'yes', or wc_tax_enabled is false, return and do nothing. if ('yes' === $this->is_vat_exempt || !wc_tax_enabled()) { return false; } if ('billing' === $tax_based_on) { $country = $this->billing_country; $state = $this->billing_state; $postcode = $this->billing_postcode; $city = $this->billing_city; } elseif ('shipping' === $tax_based_on) { $country = $this->shipping_country; $state = $this->shipping_state; $postcode = $this->shipping_postcode; $city = $this->shipping_city; } // Default to base if ('base' === $tax_based_on || empty($country)) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } // Get items foreach ($this->get_items(array('line_item', 'fee')) as $item_id => $item) { $product = $this->get_product_from_item($item); $line_total = isset($item['line_total']) ? $item['line_total'] : 0; $line_subtotal = isset($item['line_subtotal']) ? $item['line_subtotal'] : 0; $tax_class = $item['tax_class']; $item_tax_status = $product ? $product->get_tax_status() : 'taxable'; if ('0' !== $tax_class && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal, $tax_rates, false); $line_taxes = WC_Tax::calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = max(0, array_sum($line_subtotal_taxes)); $line_tax = max(0, array_sum($line_taxes)); $tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($line_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => $line_subtotal_taxes)); // Sum the item taxes foreach (array_keys($taxes + $line_taxes) as $key) { $taxes[$key] = (isset($line_taxes[$key]) ? $line_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0); } } } // Calc taxes for shipping foreach ($this->get_shipping_methods() as $item_id => $item) { $shipping_tax_class = get_option('woocommerce_shipping_tax_class'); // Inherit tax class from items if ('' === $shipping_tax_class) { $tax_classes = WC_Tax::get_tax_classes(); foreach ($tax_classes as $tax_class) { $tax_class = sanitize_title($tax_class); if (in_array($tax_class, $found_tax_classes)) { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); break; } } } else { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => 'standard' === $shipping_tax_class ? '' : $shipping_tax_class)); } $line_taxes = WC_Tax::calc_tax($item['cost'], $tax_rates, false); $line_tax = max(0, array_sum($line_taxes)); $shipping_tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes)); // Sum the item taxes foreach (array_keys($shipping_taxes + $line_taxes) as $key) { $shipping_taxes[$key] = (isset($line_taxes[$key]) ? $line_taxes[$key] : 0) + (isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0); } } // Save tax totals $this->set_total($shipping_tax_total, 'shipping_tax'); $this->set_total($tax_total, 'tax'); // Tax rows $this->remove_order_items('tax'); // Now merge to keep tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $this->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } return true; }
/** * Set tax class. * @param string $value */ public function set_tax_class($value) { if ($value && !in_array($value, WC_Tax::get_tax_classes())) { //$this->throw_exception( __METHOD__, 'Invalid tax class' ); } $this->_data['tax_class'] = $value; }
/** * @used-by callback_init_combined_tax_classes */ private static function reset_tax_classes() { $redefined = array_map('trim', array_diff(WC_Tax::get_tax_classes(), static::$predefined_tax_classes)); update_option('woocommerce_tax_classes', implode("\n", $redefined)); }
/** * Delete a single tax class. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|WP_REST_Response */ public function delete_item($request) { global $wpdb; $id = (int) $request['id']; $force = isset($request['force']) ? (bool) $request['force'] : false; // We don't support trashing for this type, error out. if (!$force) { return new WP_Error('woocommerce_rest_trash_not_supported', __('Taxes do not support trashing.', 'woocommerce'), array('status' => 501)); } $tax_class = array('slug' => sanitize_title($request['slug']), 'name' => ''); $classes = WC_Tax::get_tax_classes(); $deleted = false; foreach ($classes as $key => $class) { if (sanitize_title($class) === $tax_class['slug']) { $tax_class['name'] = $class; unset($classes[$key]); $deleted = true; break; } } if (!$deleted) { return new WP_Error('woocommerce_rest_invalid_id', __('Invalid resource id.', 'woocommerce'), array('status' => 400)); } update_option('woocommerce_tax_classes', implode("\n", $classes)); // Delete tax rate locations locations from the selected class. $wpdb->query($wpdb->prepare("\n\t\t\tDELETE locations.*\n\t\t\tFROM {$wpdb->prefix}woocommerce_tax_rate_locations AS locations\n\t\t\tINNER JOIN\n\t\t\t\t{$wpdb->prefix}woocommerce_tax_rates AS rates\n\t\t\t\tON rates.tax_rate_id = locations.tax_rate_id\n\t\t\tWHERE rates.tax_rate_class = '%s'\n\t\t", $tax_class['slug'])); // Delete tax rates in the selected class. $wpdb->delete($wpdb->prefix . 'woocommerce_tax_rates', array('tax_rate_class' => $tax_class['slug']), array('%s')); $request->set_param('context', 'edit'); $response = $this->prepare_item_for_response($tax_class, $request); /** * Fires after a tax class is deleted via the REST API. * * @param stdClass $tax_class The tax data. * @param WP_REST_Response $response The response returned from the API. * @param WP_REST_Request $request The request sent to the API. */ do_action('woocommerce_rest_delete_tax', (object) $tax_class, $response, $request); return $response; }
/** * Get the query params for collections. * * @return array */ public function get_collection_params() { $params = parent::get_collection_params(); $params['context']['default'] = 'view'; $params['exclude'] = array('description' => __('Ensure result set excludes specific IDs.', 'woocommerce'), 'type' => 'array', 'default' => array(), 'sanitize_callback' => 'wp_parse_id_list'); $params['include'] = array('description' => __('Limit result set to specific IDs.', 'woocommerce'), 'type' => 'array', 'default' => array(), 'sanitize_callback' => 'wp_parse_id_list'); $params['offset'] = array('description' => __('Offset the result set by a specific number of items.', 'woocommerce'), 'type' => 'integer', 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg'); $params['order'] = array('default' => 'asc', 'description' => __('Order sort attribute ascending or descending.', 'woocommerce'), 'enum' => array('asc', 'desc'), 'sanitize_callback' => 'sanitize_key', 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg'); $params['orderby'] = array('default' => 'order', 'description' => __('Sort collection by object attribute.', 'woocommerce'), 'enum' => array('id', 'order'), 'sanitize_callback' => 'sanitize_key', 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg'); $params['class'] = array('description' => __('Sort by tax class.', 'woocommerce'), 'enum' => array_merge(array('standard'), array_map('sanitize_title', WC_Tax::get_tax_classes())), 'sanitize_callback' => 'sanitize_title', 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg'); return $params; }
<?php if (!defined('ABSPATH')) { exit; // Exit if accessed directly } global $wpdb; // Get the payment gateway $payment_gateway = wc_get_payment_gateway_by_order($order); // Get line items $line_items = $order->get_items(apply_filters('woocommerce_admin_order_item_types', 'line_item')); $line_items_fee = $order->get_items('fee'); $line_items_shipping = $order->get_items('shipping'); if (wc_tax_enabled()) { $order_taxes = $order->get_taxes(); $tax_classes = WC_Tax::get_tax_classes(); $classes_options = array(); $classes_options[''] = __('Standard', 'woocommerce'); if (!empty($tax_classes)) { foreach ($tax_classes as $class) { $classes_options[sanitize_title($class)] = $class; } } // Older orders won't have line taxes so we need to handle them differently :( $tax_data = ''; if ($line_items) { $check_item = current($line_items); $tax_data = maybe_unserialize(isset($check_item['line_tax_data']) ? $check_item['line_tax_data'] : ''); } elseif ($line_items_shipping) { $check_item = current($line_items_shipping); $tax_data = maybe_unserialize(isset($check_item['taxes']) ? $check_item['taxes'] : '');
/** * Get the total number of tax classes * * @since 2.5.0 * * @return array */ public function get_tax_classes_count() { try { if (!current_user_can('manage_woocommerce')) { throw new WC_API_Exception('woocommerce_api_user_cannot_read_tax_classes_count', __('You do not have permission to read the tax classes count', 'woocommerce'), 401); } $total = count(WC_Tax::get_tax_classes()) + 1; // +1 for Standard Rate return array('count' => $total); } catch (WC_API_Exception $e) { return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode())); } }
/** * Output the metabox */ public static function output($post) { global $post, $thepostid; wp_nonce_field('woocommerce_save_data', 'woocommerce_meta_nonce'); $thepostid = $post->ID; if ($terms = wp_get_object_terms($post->ID, 'product_type')) { $product_type = sanitize_title(current($terms)->name); } else { $product_type = apply_filters('default_product_type', 'simple'); } $product_type_selector = apply_filters('product_type_selector', array('simple' => __('Simple product', 'woocommerce'), 'grouped' => __('Grouped product', 'woocommerce'), 'external' => __('External/Affiliate product', 'woocommerce'), 'variable' => __('Variable product', 'woocommerce')), $product_type); $type_box = '<label for="product-type"><select id="product-type" name="product-type"><optgroup label="' . __('Product Type', 'woocommerce') . '">'; foreach ($product_type_selector as $value => $label) { $type_box .= '<option value="' . esc_attr($value) . '" ' . selected($product_type, $value, false) . '>' . esc_html($label) . '</option>'; } $type_box .= '</optgroup></select></label>'; $product_type_options = apply_filters('product_type_options', array('virtual' => array('id' => '_virtual', 'wrapper_class' => 'show_if_simple', 'label' => __('Virtual', 'woocommerce'), 'description' => __('Virtual products are intangible and aren\'t shipped.', 'woocommerce'), 'default' => 'no'), 'downloadable' => array('id' => '_downloadable', 'wrapper_class' => 'show_if_simple', 'label' => __('Downloadable', 'woocommerce'), 'description' => __('Downloadable products give access to a file upon purchase.', 'woocommerce'), 'default' => 'no'))); foreach ($product_type_options as $key => $option) { $selected_value = get_post_meta($post->ID, '_' . $key, true); if ('' == $selected_value && isset($option['default'])) { $selected_value = $option['default']; } $type_box .= '<label for="' . esc_attr($option['id']) . '" class="' . esc_attr($option['wrapper_class']) . ' tips" data-tip="' . esc_attr($option['description']) . '">' . esc_html($option['label']) . ': <input type="checkbox" name="' . esc_attr($option['id']) . '" id="' . esc_attr($option['id']) . '" ' . checked($selected_value, 'yes', false) . ' /></label>'; } ?> <div class="panel-wrap product_data"> <span class="type_box"> — <?php echo $type_box; ?> </span> <ul class="product_data_tabs wc-tabs" style="display:none;"> <?php $product_data_tabs = apply_filters('woocommerce_product_data_tabs', array('general' => array('label' => __('General', 'woocommerce'), 'target' => 'general_product_data', 'class' => array('hide_if_grouped')), 'inventory' => array('label' => __('Inventory', 'woocommerce'), 'target' => 'inventory_product_data', 'class' => array('show_if_simple', 'show_if_variable', 'show_if_grouped')), 'shipping' => array('label' => __('Shipping', 'woocommerce'), 'target' => 'shipping_product_data', 'class' => array('hide_if_virtual', 'hide_if_grouped', 'hide_if_external')), 'linked_product' => array('label' => __('Linked Products', 'woocommerce'), 'target' => 'linked_product_data', 'class' => array()), 'attribute' => array('label' => __('Attributes', 'woocommerce'), 'target' => 'product_attributes', 'class' => array()), 'variations' => array('label' => __('Variations', 'woocommerce'), 'target' => 'variable_product_options', 'class' => array('variations_tab', 'show_if_variable')), 'advanced' => array('label' => __('Advanced', 'woocommerce'), 'target' => 'advanced_product_data', 'class' => array()))); foreach ($product_data_tabs as $key => $tab) { ?> <li class="<?php echo $key; ?> _options <?php echo $key; ?> _tab <?php echo implode(' ', $tab['class']); ?> "> <a href="#<?php echo $tab['target']; ?> "><?php echo esc_html($tab['label']); ?> </a> </li><?php } do_action('woocommerce_product_write_panel_tabs'); ?> </ul> <div id="general_product_data" class="panel woocommerce_options_panel"><?php echo '<div class="options_group hide_if_grouped">'; // SKU if (wc_product_sku_enabled()) { woocommerce_wp_text_input(array('id' => '_sku', 'label' => '<abbr title="' . __('Stock Keeping Unit', 'woocommerce') . '">' . __('SKU', 'woocommerce') . '</abbr>', 'desc_tip' => 'true', 'description' => __('SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce'))); } else { echo '<input type="hidden" name="_sku" value="' . esc_attr(get_post_meta($thepostid, '_sku', true)) . '" />'; } do_action('woocommerce_product_options_sku'); echo '</div>'; echo '<div class="options_group show_if_external">'; // External URL woocommerce_wp_text_input(array('id' => '_product_url', 'label' => __('Product URL', 'woocommerce'), 'placeholder' => 'http://', 'description' => __('Enter the external URL to the product.', 'woocommerce'))); // Button text woocommerce_wp_text_input(array('id' => '_button_text', 'label' => __('Button text', 'woocommerce'), 'placeholder' => _x('Buy product', 'placeholder', 'woocommerce'), 'description' => __('This text will be shown on the button linking to the external product.', 'woocommerce'))); echo '</div>'; echo '<div class="options_group pricing show_if_simple show_if_external">'; // Price woocommerce_wp_text_input(array('id' => '_regular_price', 'label' => __('Regular Price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')', 'data_type' => 'price')); // Special Price woocommerce_wp_text_input(array('id' => '_sale_price', 'data_type' => 'price', 'label' => __('Sale Price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')', 'description' => '<a href="#" class="sale_schedule">' . __('Schedule', 'woocommerce') . '</a>')); // Special Price date range $sale_price_dates_from = ($date = get_post_meta($thepostid, '_sale_price_dates_from', true)) ? date_i18n('Y-m-d', $date) : ''; $sale_price_dates_to = ($date = get_post_meta($thepostid, '_sale_price_dates_to', true)) ? date_i18n('Y-m-d', $date) : ''; echo '<p class="form-field sale_price_dates_fields"> <label for="_sale_price_dates_from">' . __('Sale Price Dates', 'woocommerce') . '</label> <input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr($sale_price_dates_from) . '" placeholder="' . _x('From…', 'placeholder', 'woocommerce') . ' YYYY-MM-DD" maxlength="10" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" /> <input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr($sale_price_dates_to) . '" placeholder="' . _x('To…', 'placeholder', 'woocommerce') . ' YYYY-MM-DD" maxlength="10" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" /> <a href="#" class="cancel_sale_schedule">' . __('Cancel', 'woocommerce') . '</a> <img class="help_tip" style="margin-top: 21px;" data-tip="' . __('The sale will end at the beginning of the set date.', 'woocommerce') . '" src="' . esc_url(WC()->plugin_url()) . '/assets/images/help.png" height="16" width="16" /> </p>'; do_action('woocommerce_product_options_pricing'); echo '</div>'; echo '<div class="options_group show_if_downloadable">'; ?> <div class="form-field downloadable_files"> <label><?php _e('Downloadable Files', 'woocommerce'); ?> :</label> <table class="widefat"> <thead> <tr> <th class="sort"> </th> <th><?php _e('Name', 'woocommerce'); ?> <span class="tips" data-tip="<?php _e('This is the name of the download shown to the customer.', 'woocommerce'); ?> ">[?]</span></th> <th colspan="2"><?php _e('File URL', 'woocommerce'); ?> <span class="tips" data-tip="<?php _e('This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce'); ?> ">[?]</span></th> <th> </th> </tr> </thead> <tbody> <?php $downloadable_files = get_post_meta($post->ID, '_downloadable_files', true); if ($downloadable_files) { foreach ($downloadable_files as $key => $file) { include 'views/html-product-download.php'; } } ?> </tbody> <tfoot> <tr> <th colspan="5"> <a href="#" class="button insert" data-row="<?php $file = array('file' => '', 'name' => ''); ob_start(); include 'views/html-product-download.php'; echo esc_attr(ob_get_clean()); ?> "><?php _e('Add File', 'woocommerce'); ?> </a> </th> </tr> </tfoot> </table> </div> <?php // Download Limit woocommerce_wp_text_input(array('id' => '_download_limit', 'label' => __('Download Limit', 'woocommerce'), 'placeholder' => __('Unlimited', 'woocommerce'), 'description' => __('Leave blank for unlimited re-downloads.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => '1', 'min' => '0'))); // Expirey woocommerce_wp_text_input(array('id' => '_download_expiry', 'label' => __('Download Expiry', 'woocommerce'), 'placeholder' => __('Never', 'woocommerce'), 'description' => __('Enter the number of days before a download link expires, or leave blank.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => '1', 'min' => '0'))); // Download Type woocommerce_wp_select(array('id' => '_download_type', 'label' => __('Download Type', 'woocommerce'), 'description' => sprintf(__('Choose a download type - this controls the <a href="%s">schema</a>.', 'woocommerce'), 'http://schema.org/'), 'options' => array('' => __('Standard Product', 'woocommerce'), 'application' => __('Application/Software', 'woocommerce'), 'music' => __('Music', 'woocommerce')))); do_action('woocommerce_product_options_downloads'); echo '</div>'; if (wc_tax_enabled()) { echo '<div class="options_group show_if_simple show_if_external show_if_variable">'; // Tax woocommerce_wp_select(array('id' => '_tax_status', 'label' => __('Tax Status', 'woocommerce'), 'options' => array('taxable' => __('Taxable', 'woocommerce'), 'shipping' => __('Shipping only', 'woocommerce'), 'none' => _x('None', 'Tax status', 'woocommerce')))); $tax_classes = WC_Tax::get_tax_classes(); $classes_options = array(); $classes_options[''] = __('Standard', 'woocommerce'); if (!empty($tax_classes)) { foreach ($tax_classes as $class) { $classes_options[sanitize_title($class)] = esc_html($class); } } woocommerce_wp_select(array('id' => '_tax_class', 'label' => __('Tax Class', 'woocommerce'), 'options' => $classes_options)); do_action('woocommerce_product_options_tax'); echo '</div>'; } do_action('woocommerce_product_options_general_product_data'); ?> </div> <div id="inventory_product_data" class="panel woocommerce_options_panel"> <?php echo '<div class="options_group">'; if ('yes' == get_option('woocommerce_manage_stock')) { // manage stock woocommerce_wp_checkbox(array('id' => '_manage_stock', 'wrapper_class' => 'show_if_simple show_if_variable', 'label' => __('Manage stock?', 'woocommerce'), 'description' => __('Enable stock management at product level', 'woocommerce'))); do_action('woocommerce_product_options_stock'); echo '<div class="stock_fields show_if_simple show_if_variable">'; // Stock woocommerce_wp_text_input(array('id' => '_stock', 'label' => __('Stock Qty', 'woocommerce'), 'desc_tip' => true, 'description' => __('Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce'), 'type' => 'number', 'custom_attributes' => array('step' => 'any'), 'data_type' => 'stock')); // Backorders? woocommerce_wp_select(array('id' => '_backorders', 'label' => __('Allow Backorders?', 'woocommerce'), 'options' => array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce')), 'desc_tip' => true, 'description' => __('If managing stock, this controls whether or not backorders are allowed. If enabled, stock quantity can go below 0.', 'woocommerce'))); do_action('woocommerce_product_options_stock_fields'); echo '</div>'; } // Stock status woocommerce_wp_select(array('id' => '_stock_status', 'wrapper_class' => 'hide_if_variable', 'label' => __('Stock status', 'woocommerce'), 'options' => array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce')), 'desc_tip' => true, 'description' => __('Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce'))); do_action('woocommerce_product_options_stock_status'); echo '</div>'; echo '<div class="options_group show_if_simple show_if_variable">'; // Individual product woocommerce_wp_checkbox(array('id' => '_sold_individually', 'wrapper_class' => 'show_if_simple show_if_variable', 'label' => __('Sold Individually', 'woocommerce'), 'description' => __('Enable this to only allow one of this item to be bought in a single order', 'woocommerce'))); do_action('woocommerce_product_options_sold_individually'); echo '</div>'; do_action('woocommerce_product_options_inventory_product_data'); ?> </div> <div id="shipping_product_data" class="panel woocommerce_options_panel"> <?php echo '<div class="options_group">'; // Weight if (wc_product_weight_enabled()) { woocommerce_wp_text_input(array('id' => '_weight', 'label' => __('Weight', 'woocommerce') . ' (' . get_option('woocommerce_weight_unit') . ')', 'placeholder' => wc_format_localized_decimal(0), 'desc_tip' => 'true', 'description' => __('Weight in decimal form', 'woocommerce'), 'type' => 'text', 'data_type' => 'decimal')); } // Size fields if (wc_product_dimensions_enabled()) { ?> <p class="form-field dimensions_field"> <label for="product_length"><?php echo __('Dimensions', 'woocommerce') . ' (' . get_option('woocommerce_dimension_unit') . ')'; ?> </label> <span class="wrap"> <input id="product_length" placeholder="<?php _e('Length', 'woocommerce'); ?> " class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_length', true))); ?> " /> <input placeholder="<?php _e('Width', 'woocommerce'); ?> " class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_width', true))); ?> " /> <input placeholder="<?php _e('Height', 'woocommerce'); ?> " class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php echo esc_attr(wc_format_localized_decimal(get_post_meta($thepostid, '_height', true))); ?> " /> </span> <img class="help_tip" data-tip="<?php esc_attr_e('LxWxH in decimal form', 'woocommerce'); ?> " src="<?php echo esc_url(WC()->plugin_url()); ?> /assets/images/help.png" height="16" width="16" /> </p><?php } do_action('woocommerce_product_options_dimensions'); echo '</div>'; echo '<div class="options_group">'; // Shipping Class $classes = get_the_terms($thepostid, 'product_shipping_class'); if ($classes && !is_wp_error($classes)) { $current_shipping_class = current($classes)->term_id; } else { $current_shipping_class = ''; } $args = array('taxonomy' => 'product_shipping_class', 'hide_empty' => 0, 'show_option_none' => __('No shipping class', 'woocommerce'), 'name' => 'product_shipping_class', 'id' => 'product_shipping_class', 'selected' => $current_shipping_class, 'class' => 'select short'); ?> <p class="form-field dimensions_field"><label for="product_shipping_class"><?php _e('Shipping class', 'woocommerce'); ?> </label> <?php wp_dropdown_categories($args); ?> <img class="help_tip" data-tip="<?php esc_attr_e('Shipping classes are used by certain shipping methods to group similar products.', 'woocommerce'); ?> " src="<?php echo esc_url(WC()->plugin_url()); ?> /assets/images/help.png" height="16" width="16" /></p><?php do_action('woocommerce_product_options_shipping'); echo '</div>'; ?> </div> <div id="product_attributes" class="panel wc-metaboxes-wrapper"> <div class="product_attributes wc-metaboxes"> <?php global $wc_product_attributes; // Array of defined attribute taxonomies $attribute_taxonomies = wc_get_attribute_taxonomies(); // Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set $attributes = maybe_unserialize(get_post_meta($thepostid, '_product_attributes', true)); // Output All Set Attributes if (!empty($attributes)) { $attribute_keys = array_keys($attributes); $attribute_total = sizeof($attribute_keys); for ($i = 0; $i < $attribute_total; $i++) { $attribute = $attributes[$attribute_keys[$i]]; $position = empty($attribute['position']) ? 0 : absint($attribute['position']); $taxonomy = ''; $metabox_class = array(); if ($attribute['is_taxonomy']) { $taxonomy = $attribute['name']; if (!taxonomy_exists($taxonomy)) { continue; } $attribute_taxonomy = $wc_product_attributes[$taxonomy]; $metabox_class[] = 'taxonomy'; $metabox_class[] = $taxonomy; $attribute_label = wc_attribute_label($taxonomy); } else { $attribute_label = apply_filters('woocommerce_attribute_label', $attribute['name'], $attribute['name']); } include 'views/html-product-attribute.php'; } } ?> </div> <p class="toolbar"> <button type="button" class="button button-primary add_attribute"><?php _e('Add', 'woocommerce'); ?> </button> <select name="attribute_taxonomy" class="attribute_taxonomy"> <option value=""><?php _e('Custom product attribute', 'woocommerce'); ?> </option> <?php if ($attribute_taxonomies) { foreach ($attribute_taxonomies as $tax) { $attribute_taxonomy_name = wc_attribute_taxonomy_name($tax->attribute_name); $label = $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name; echo '<option value="' . esc_attr($attribute_taxonomy_name) . '">' . esc_html($label) . '</option>'; } } ?> </select> <button type="button" class="button save_attributes"><?php _e('Save attributes', 'woocommerce'); ?> </button> </p> <?php do_action('woocommerce_product_options_attributes'); ?> </div> <div id="linked_product_data" class="panel woocommerce_options_panel"> <div class="options_group"> <p class="form-field"> <label for="upsell_ids"><?php _e('Up-Sells', 'woocommerce'); ?> </label> <input type="hidden" class="wc-product-search" style="width: 50%;" id="upsell_ids" name="upsell_ids" data-placeholder="<?php _e('Search for a product…', 'woocommerce'); ?> " data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php echo intval($post->ID); ?> " data-selected="<?php $product_ids = array_filter(array_map('absint', (array) get_post_meta($post->ID, '_upsell_ids', true))); $json_ids = array(); foreach ($product_ids as $product_id) { $product = wc_get_product($product_id); if (is_object($product)) { $json_ids[$product_id] = wp_kses_post(html_entity_decode($product->get_formatted_name())); } } echo esc_attr(json_encode($json_ids)); ?> " value="<?php echo implode(',', array_keys($json_ids)); ?> " /> <img class="help_tip" data-tip='<?php _e('Up-sells are products which you recommend instead of the currently viewed product, for example, products that are more profitable or better quality or more expensive.', 'woocommerce'); ?> ' src="<?php echo WC()->plugin_url(); ?> /assets/images/help.png" height="16" width="16" /> </p> <p class="form-field"> <label for="crosssell_ids"><?php _e('Cross-Sells', 'woocommerce'); ?> </label> <input type="hidden" class="wc-product-search" style="width: 50%;" id="crosssell_ids" name="crosssell_ids" data-placeholder="<?php _e('Search for a product…', 'woocommerce'); ?> " data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php echo intval($post->ID); ?> " data-selected="<?php $product_ids = array_filter(array_map('absint', (array) get_post_meta($post->ID, '_crosssell_ids', true))); $json_ids = array(); foreach ($product_ids as $product_id) { $product = wc_get_product($product_id); if (is_object($product)) { $json_ids[$product_id] = wp_kses_post(html_entity_decode($product->get_formatted_name())); } } echo esc_attr(json_encode($json_ids)); ?> " value="<?php echo implode(',', array_keys($json_ids)); ?> " /> <img class="help_tip" data-tip='<?php _e('Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce'); ?> ' src="<?php echo WC()->plugin_url(); ?> /assets/images/help.png" height="16" width="16" /> </p> </div> <div class="options_group grouping show_if_simple show_if_external"> <p class="form-field"> <label for="parent_id"><?php _e('Grouping', 'woocommerce'); ?> </label> <input type="hidden" class="wc-product-search" style="width: 50%;" id="parent_id" name="parent_id" data-placeholder="<?php _e('Search for a product…', 'woocommerce'); ?> " data-action="woocommerce_json_search_grouped_products" data-allow_clear="true" data-multiple="false" data-exclude="<?php echo intval($post->ID); ?> " data-selected="<?php $parent_id = absint($post->post_parent); if ($parent_id) { $parent = wc_get_product($parent_id); if (is_object($parent)) { $parent_title = wp_kses_post(html_entity_decode($parent->get_formatted_name())); } echo esc_attr($parent_title); } ?> " value="<?php echo $parent_id ? $parent_id : ''; ?> " /> <img class="help_tip" data-tip='<?php _e('Set this option to make this product part of a grouped product.', 'woocommerce'); ?> ' src="<?php echo WC()->plugin_url(); ?> /assets/images/help.png" height="16" width="16" /> </p> <?php woocommerce_wp_hidden_input(array('id' => 'previous_parent_id', 'value' => absint($post->post_parent))); do_action('woocommerce_product_options_grouping'); ?> </div> <?php do_action('woocommerce_product_options_related'); ?> </div> <div id="advanced_product_data" class="panel woocommerce_options_panel"> <div class="options_group hide_if_external"> <?php // Purchase note woocommerce_wp_textarea_input(array('id' => '_purchase_note', 'label' => __('Purchase Note', 'woocommerce'), 'desc_tip' => 'true', 'description' => __('Enter an optional note to send the customer after purchase.', 'woocommerce'))); ?> </div> <div class="options_group"> <?php // menu_order woocommerce_wp_text_input(array('id' => 'menu_order', 'label' => __('Menu order', 'woocommerce'), 'desc_tip' => 'true', 'description' => __('Custom ordering position.', 'woocommerce'), 'value' => intval($post->menu_order), 'type' => 'number', 'custom_attributes' => array('step' => '1'))); ?> </div> <div class="options_group reviews"> <?php woocommerce_wp_checkbox(array('id' => 'comment_status', 'label' => __('Enable reviews', 'woocommerce'), 'cbvalue' => 'open', 'value' => esc_attr($post->comment_status))); do_action('woocommerce_product_options_reviews'); ?> </div> <?php do_action('woocommerce_product_options_advanced'); ?> </div> <?php self::output_variations(); do_action('woocommerce_product_data_panels'); do_action('woocommerce_product_write_panels'); // _deprecated ?> <div class="clear"></div> </div> <?php }
/** * 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(); } }
/** * 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); }
/** * Load variations via AJAX */ public static function load_variations() { ob_start(); check_ajax_referer('load-variations', 'security'); // Check permissions again and make sure we have what we need if (!current_user_can('edit_products') || empty($_POST['product_id']) || empty($_POST['attributes'])) { die(-1); } global $post; $product_id = absint($_POST['product_id']); $post = get_post($product_id); // Set $post global so its available like within the admin screens $per_page = !empty($_POST['per_page']) ? absint($_POST['per_page']) : 10; $page = !empty($_POST['page']) ? absint($_POST['page']) : 1; // Get attributes $attributes = array(); foreach ($_POST['attributes'] as $key => $value) { $attributes[wc_clean($key)] = array_map('wc_clean', $value); } // Get tax classes $tax_classes = WC_Tax::get_tax_classes(); $tax_class_options = array(); $tax_class_options[''] = __('Standard', 'woocommerce'); if (!empty($tax_classes)) { foreach ($tax_classes as $class) { $tax_class_options[sanitize_title($class)] = esc_attr($class); } } // Set backorder options $backorder_options = array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce')); // set stock status options $stock_status_options = array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce')); $parent_data = array('id' => $product_id, 'attributes' => $attributes, 'tax_class_options' => $tax_class_options, 'sku' => get_post_meta($product_id, '_sku', true), 'weight' => wc_format_localized_decimal(get_post_meta($product_id, '_weight', true)), 'length' => wc_format_localized_decimal(get_post_meta($product_id, '_length', true)), 'width' => wc_format_localized_decimal(get_post_meta($product_id, '_width', true)), 'height' => wc_format_localized_decimal(get_post_meta($product_id, '_height', true)), 'tax_class' => get_post_meta($product_id, '_tax_class', true), 'backorder_options' => $backorder_options, 'stock_status_options' => $stock_status_options); if (!$parent_data['weight']) { $parent_data['weight'] = wc_format_localized_decimal(0); } if (!$parent_data['length']) { $parent_data['length'] = wc_format_localized_decimal(0); } if (!$parent_data['width']) { $parent_data['width'] = wc_format_localized_decimal(0); } if (!$parent_data['height']) { $parent_data['height'] = wc_format_localized_decimal(0); } // Get variations $args = array('post_type' => 'product_variation', 'post_status' => array('private', 'publish'), 'posts_per_page' => $per_page, 'paged' => $page, 'orderby' => 'ID', 'order' => 'DESC', 'post_parent' => $product_id); $variations = get_posts($args); $loop = 0; if ($variations) { foreach ($variations as $variation) { $variation_id = absint($variation->ID); $variation_meta = get_post_meta($variation_id); $variation_data = array(); $shipping_classes = get_the_terms($variation_id, 'product_shipping_class'); $variation_fields = array('_sku' => '', '_stock' => '', '_regular_price' => '', '_sale_price' => '', '_weight' => '', '_length' => '', '_width' => '', '_height' => '', '_download_limit' => '', '_download_expiry' => '', '_downloadable_files' => '', '_downloadable' => '', '_virtual' => '', '_thumbnail_id' => '', '_sale_price_dates_from' => '', '_sale_price_dates_to' => '', '_manage_stock' => '', '_stock_status' => '', '_backorders' => null, '_tax_class' => null, '_variation_description' => ''); foreach ($variation_fields as $field => $value) { $variation_data[$field] = isset($variation_meta[$field][0]) ? maybe_unserialize($variation_meta[$field][0]) : $value; } // Add the variation attributes foreach ($variation_meta as $key => $value) { if (0 !== strpos($key, 'attribute_')) { continue; } /** * Pre 2.4 handling where 'slugs' were saved instead of the full text attribute. * Attempt to get full version of the text attribute from the parent. */ if (sanitize_title($value[0]) === $value[0] && version_compare(get_post_meta($product_id, '_product_version', true), '2.4.0', '<')) { foreach ($attributes as $attribute) { if ($key !== 'attribute_' . sanitize_title($attribute['name'])) { continue; } $text_attributes = wc_get_text_attributes($attribute['value']); foreach ($text_attributes as $text_attribute) { if (sanitize_title($text_attribute) === $value[0]) { $value[0] = $text_attribute; } } } } $variation_data[$key] = $value[0]; } // Formatting $variation_data['_regular_price'] = wc_format_localized_price($variation_data['_regular_price']); $variation_data['_sale_price'] = wc_format_localized_price($variation_data['_sale_price']); $variation_data['_weight'] = wc_format_localized_decimal($variation_data['_weight']); $variation_data['_length'] = wc_format_localized_decimal($variation_data['_length']); $variation_data['_width'] = wc_format_localized_decimal($variation_data['_width']); $variation_data['_height'] = wc_format_localized_decimal($variation_data['_height']); $variation_data['_thumbnail_id'] = absint($variation_data['_thumbnail_id']); $variation_data['image'] = $variation_data['_thumbnail_id'] ? wp_get_attachment_thumb_url($variation_data['_thumbnail_id']) : ''; $variation_data['shipping_class'] = $shipping_classes && !is_wp_error($shipping_classes) ? current($shipping_classes)->term_id : ''; // Stock BW compat if ('' !== $variation_data['_stock']) { $variation_data['_manage_stock'] = 'yes'; } include 'admin/meta-boxes/views/html-variation-admin.php'; $loop++; } } die; }
/** * Add variation via ajax function */ public static function add_variation() { check_ajax_referer('add-variation', 'security'); $post_id = intval($_POST['post_id']); $loop = intval($_POST['loop']); $variation = array('post_title' => 'Product #' . $post_id . ' Variation', 'post_content' => '', 'post_status' => 'publish', 'post_author' => get_current_user_id(), 'post_parent' => $post_id, 'post_type' => 'product_variation'); $variation_id = wp_insert_post($variation); do_action('woocommerce_create_product_variation', $variation_id); if ($variation_id) { $variation_post_status = 'publish'; $variation_data = get_post_meta($variation_id); $variation_data['variation_post_id'] = $variation_id; // Get attributes $attributes = (array) maybe_unserialize(get_post_meta($post_id, '_product_attributes', true)); // Get tax classes $tax_classes = WC_Tax::get_tax_classes(); $tax_class_options = array(); $tax_class_options['parent'] = __('Same as parent', 'woocommerce'); $tax_class_options[''] = __('Standard', 'woocommerce'); if ($tax_classes) { foreach ($tax_classes as $class) { $tax_class_options[sanitize_title($class)] = $class; } } $backorder_options = array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce')); $stock_status_options = array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce')); // Get parent data $parent_data = array('id' => $post_id, 'attributes' => $attributes, 'tax_class_options' => $tax_class_options, 'sku' => get_post_meta($post_id, '_sku', true), 'weight' => get_post_meta($post_id, '_weight', true), 'length' => get_post_meta($post_id, '_length', true), 'width' => get_post_meta($post_id, '_width', true), 'height' => get_post_meta($post_id, '_height', true), 'tax_class' => get_post_meta($post_id, '_tax_class', true), 'backorder_options' => $backorder_options, 'stock_status_options' => $stock_status_options); if (!$parent_data['weight']) { $parent_data['weight'] = '0.00'; } if (!$parent_data['length']) { $parent_data['length'] = '0'; } if (!$parent_data['width']) { $parent_data['width'] = '0'; } if (!$parent_data['height']) { $parent_data['height'] = '0'; } $_tax_class = ''; $_downloadable_files = ''; $_stock_status = ''; $_backorders = ''; $image_id = 0; $_thumbnail_id = ''; $variation = get_post($variation_id); // Get the variation object include 'admin/meta-boxes/views/html-variation-admin.php'; } die; }
/** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * Will use the base country unless customer addresses are set. * @param $args array Added in 2.7.0 to pass things like location. */ public function calculate_taxes($args = array()) { $tax_based_on = get_option('woocommerce_tax_based_on'); $args = wp_parse_args($args, array('country' => 'billing' === $tax_based_on ? $this->get_billing_country() : $this->get_shipping_country(), 'state' => 'billing' === $tax_based_on ? $this->get_billing_state() : $this->get_shipping_state(), 'postcode' => 'billing' === $tax_based_on ? $this->get_billing_postcode() : $this->get_shipping_postcode(), 'city' => 'billing' === $tax_based_on ? $this->get_billing_city() : $this->get_shipping_city())); // Default to base if ('base' === $tax_based_on || empty($args['country'])) { $default = wc_get_base_location(); $args['country'] = $default['country']; $args['state'] = $default['state']; $args['postcode'] = ''; $args['city'] = ''; } // Calc taxes for line items foreach ($this->get_items(array('line_item', 'fee')) as $item_id => $item) { $tax_class = $item->get_tax_class(); $tax_status = $item->get_tax_status(); if ('0' !== $tax_class && 'taxable' === $tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => $tax_class)); $total = $item->get_total(); $taxes = WC_Tax::calc_tax($total, $tax_rates, false); if ($item->is_type('line_item')) { $subtotal = $item->get_subtotal(); $subtotal_taxes = WC_Tax::calc_tax($subtotal, $tax_rates, false); $item->set_taxes(array('total' => $taxes, 'subtotal' => $subtotal_taxes)); } else { $item->set_taxes(array('total' => $taxes)); } $item->save(); } } // Calc taxes for shipping foreach ($this->get_shipping_methods() as $item_id => $item) { $shipping_tax_class = get_option('woocommerce_shipping_tax_class'); // Inherit tax class from items if ('' === $shipping_tax_class) { $tax_rates = array(); $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $found_tax_classes = $this->get_items_tax_classes(); foreach ($tax_classes as $tax_class) { $tax_class = sanitize_title($tax_class); if (in_array($tax_class, $found_tax_classes)) { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => $tax_class)); break; } } } else { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => 'standard' === $shipping_tax_class ? '' : $shipping_tax_class)); } $item->set_taxes(array('total' => WC_Tax::calc_tax($item->get_total(), $tax_rates, false))); $item->save(); } $this->update_taxes(); }
/** * 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); }
/** * 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(); }
/** * List tax classes. * * ## OPTIONS * * [--<field>=<value>] * : Filter tax class based on tax class property. * * [--field=<field>] * : Prints the value of a single field for each tax class. * * [--fields=<fields>] * : Limit the output to specific tax class fields. * * [--format=<format>] * : Acceptec values: table, csv, json, count, ids. Default: table. * * ## AVAILABLE FIELDS * * These fields will be displayed by default for each tax class: * * * slug * * name * * ## EXAMPLES * * wp wc tax list_class * * wp wc tax list_class --field=slug * * wp wc tax list_class --format=json * * @since 2.5.0 * @subcommand list_class */ public function list_class($__, $assoc_args) { // Set default fields for tax classes if (empty($assoc_args['fields'])) { $assoc_args['fields'] = 'slug,name'; } $formatter = $this->get_formatter($assoc_args); $items = array(); // Add standard class $items[] = array('slug' => 'standard', 'name' => __('Standard Rate', 'woocommerce')); $classes = WC_Tax::get_tax_classes(); foreach ($classes as $class) { $items[] = apply_filters('woocommerce_cli_tax_class_response', array('slug' => sanitize_title($class), 'name' => $class), $class, $assoc_args, $this); } if ('ids' === $formatter->format) { $_slugs = array(); foreach ($items as $item) { $_slugs[] = $item['slug']; } echo implode(' ', $_slugs); } else { $formatter->display_items($items); } }