Ability to make layered nav an "OR" query so you can expand your search rather than filter it. Closes #47.
This commit is contained in:
parent
80cfc09956
commit
9ee4460516
|
@ -9,11 +9,11 @@
|
|||
*/
|
||||
class woocommerce_query {
|
||||
|
||||
var $unfiltered_product_ids = array(); // Unfilted product ids (before layered nav etc)
|
||||
var $filtered_product_ids = array(); // Filted product ids (after layered nav)
|
||||
var $post__in = array(); // Product id's that match the layered nav + price filter
|
||||
var $unfiltered_product_ids = array(); // Unfiltered product ids (before layered nav etc)
|
||||
var $filtered_product_ids = array(); // Filtered product ids (after layered nav)
|
||||
var $post__in = array(); // Product id's that match the layered nav + price filter
|
||||
var $meta_query = ''; // The meta query for the page
|
||||
var $layered_nav_post__in = array(); // posts matching layered nav only
|
||||
var $layered_nav_post__in = array(); // posts matching layered nav only
|
||||
var $layered_nav_product_ids = array(); // Stores posts matching layered nav, so price filter can find max price in view
|
||||
|
||||
/** constructor */
|
||||
|
|
|
@ -96,6 +96,7 @@ Yes you can! Join in on our GitHub repository :) https://github.com/woothemes/wo
|
|||
* Ability to register from my account page
|
||||
* Option to show size/weight on attributes tab
|
||||
* Added logger class for debugging
|
||||
* Ability to make layered nav an "OR" query so you can expand your search rather than filter it
|
||||
|
||||
= 1.2.1 - 10/11/2011 =
|
||||
* Reworked downloadable and virtual products - now variations can be downloadable/virtual too making it more flexible
|
||||
|
|
|
@ -25,8 +25,16 @@ function woocommerce_layered_nav_init() {
|
|||
$attribute = strtolower(sanitize_title($tax->attribute_name));
|
||||
$taxonomy = $woocommerce->attribute_taxonomy_name($attribute);
|
||||
$name = 'filter_' . $attribute;
|
||||
$query_type_name = 'query_type_' . $attribute;
|
||||
|
||||
if (isset($_GET[$name]) && taxonomy_exists($taxonomy)) $_chosen_attributes[$taxonomy] = explode(',', $_GET[$name] );
|
||||
if (isset($_GET[$name]) && taxonomy_exists($taxonomy)) :
|
||||
$_chosen_attributes[$taxonomy]['terms'] = explode(',', $_GET[$name] );
|
||||
if (isset($_GET[$query_type_name]) && $_GET[$query_type_name]=='or') :
|
||||
$_chosen_attributes[$taxonomy]['query_type'] = 'or';
|
||||
else :
|
||||
$_chosen_attributes[$taxonomy]['query_type'] = 'and';
|
||||
endif;
|
||||
endif;
|
||||
|
||||
endforeach;
|
||||
endif;
|
||||
|
@ -45,23 +53,50 @@ function woocommerce_layered_nav_query( $filtered_posts ) {
|
|||
if (sizeof($_chosen_attributes)>0) :
|
||||
|
||||
$matched_products = array();
|
||||
$filtered = false;
|
||||
$filtered_attribute = false;
|
||||
|
||||
foreach ($_chosen_attributes as $attribute => $values) :
|
||||
if (sizeof($values)>0) :
|
||||
foreach ($values as $value) :
|
||||
foreach ($_chosen_attributes as $attribute => $data) :
|
||||
|
||||
$matched_products_from_attribute = array();
|
||||
$filtered = false;
|
||||
|
||||
if (sizeof($data['terms'])>0) :
|
||||
foreach ($data['terms'] as $value) :
|
||||
|
||||
$posts = get_objects_in_term( $value, $attribute );
|
||||
if (!is_wp_error($posts) && (sizeof($matched_products)>0 || $filtered)) :
|
||||
$matched_products = array_intersect($posts, $matched_products);
|
||||
elseif (!is_wp_error($posts)) :
|
||||
$matched_products = $posts;
|
||||
|
||||
// AND or OR
|
||||
if ($data['query_type']=='or') :
|
||||
|
||||
if (!is_wp_error($posts) && (sizeof($matched_products_from_attribute)>0 || $filtered)) :
|
||||
$matched_products_from_attribute = array_merge($posts, $matched_products_from_attribute);
|
||||
elseif (!is_wp_error($posts)) :
|
||||
$matched_products_from_attribute = $posts;
|
||||
endif;
|
||||
|
||||
else :
|
||||
|
||||
if (!is_wp_error($posts) && (sizeof($matched_products_from_attribute)>0 || $filtered)) :
|
||||
$matched_products_from_attribute = array_intersect($posts, $matched_products_from_attribute);
|
||||
elseif (!is_wp_error($posts)) :
|
||||
$matched_products_from_attribute = $posts;
|
||||
endif;
|
||||
|
||||
endif;
|
||||
|
||||
$filtered = true;
|
||||
|
||||
endforeach;
|
||||
endif;
|
||||
|
||||
if (sizeof($matched_products)>0 || $filtered_attribute) :
|
||||
$matched_products = array_intersect($matched_products_from_attribute, $matched_products);
|
||||
else :
|
||||
$matched_products = $matched_products_from_attribute;
|
||||
endif;
|
||||
|
||||
$filtered_attribute = true;
|
||||
|
||||
endforeach;
|
||||
|
||||
if ($filtered) :
|
||||
|
@ -119,18 +154,18 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
|
||||
global $_chosen_attributes, $woocommerce, $wp_query;
|
||||
|
||||
$title = $instance['title'];
|
||||
$taxonomy = $woocommerce->attribute_taxonomy_name($instance['attribute']);
|
||||
$title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
||||
$taxonomy = $woocommerce->attribute_taxonomy_name($instance['attribute']);
|
||||
$query_type = (isset($instance['query_type'])) ? $instance['query_type'] : 'and';
|
||||
|
||||
if (!taxonomy_exists($taxonomy)) return;
|
||||
|
||||
$title = apply_filters('widget_title', $title, $instance, $this->id_base);
|
||||
|
||||
$args = array(
|
||||
'hide_empty' => '1'
|
||||
);
|
||||
$terms = get_terms( $taxonomy, $args );
|
||||
$count = count($terms);
|
||||
|
||||
if($count > 0){
|
||||
|
||||
$found = false;
|
||||
|
@ -155,13 +190,25 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
set_transient( $transient_name, $_products_in_term );
|
||||
}
|
||||
|
||||
$count = sizeof(array_intersect($_products_in_term, $woocommerce->query->filtered_product_ids));
|
||||
$option_is_set = (isset($_chosen_attributes[$taxonomy]) && in_array($term->term_id, $_chosen_attributes[$taxonomy]['terms']));
|
||||
|
||||
// If this is an AND query, only show options with count > 0
|
||||
if ($query_type=='and') {
|
||||
|
||||
$count = sizeof(array_intersect($_products_in_term, $woocommerce->query->filtered_product_ids));
|
||||
|
||||
if ($count>0) $found = true;
|
||||
if ($count>0) $found = true;
|
||||
|
||||
$option_is_set = (isset($_chosen_attributes[$taxonomy]) && in_array($term->term_id, $_chosen_attributes[$taxonomy]));
|
||||
if ($count==0 && !$option_is_set) continue;
|
||||
|
||||
if ($count==0 && !$option_is_set) continue;
|
||||
// If this is an OR query, show all options so search can be expanded
|
||||
} else {
|
||||
|
||||
$count = sizeof(array_intersect($_products_in_term, $woocommerce->query->unfiltered_product_ids));
|
||||
|
||||
if ($count>0) $found = true;
|
||||
|
||||
}
|
||||
|
||||
$class = '';
|
||||
|
||||
|
@ -183,9 +230,10 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
endif;
|
||||
|
||||
// All current filters
|
||||
if ($_chosen_attributes) foreach ($_chosen_attributes as $name => $value) :
|
||||
if ($_chosen_attributes) foreach ($_chosen_attributes as $name => $data) :
|
||||
if ($name!==$taxonomy) :
|
||||
$link = add_query_arg( strtolower(sanitize_title(str_replace('pa_', 'filter_', $name))), implode(',', $value), $link );
|
||||
$link = add_query_arg( strtolower(sanitize_title(str_replace('pa_', 'filter_', $name))), implode(',', $data['terms']), $link );
|
||||
if ($data['query_type']=='or') $link = add_query_arg( strtolower(sanitize_title(str_replace('pa_', 'query_type_', $name))), 'or', $link );
|
||||
endif;
|
||||
endforeach;
|
||||
|
||||
|
@ -198,7 +246,7 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
endif;
|
||||
|
||||
// Current Filter = this widget
|
||||
if (isset( $_chosen_attributes[$taxonomy] ) && is_array($_chosen_attributes[$taxonomy]) && in_array($term->term_id, $_chosen_attributes[$taxonomy])) :
|
||||
if (isset( $_chosen_attributes[$taxonomy] ) && is_array($_chosen_attributes[$taxonomy]['terms']) && in_array($term->term_id, $_chosen_attributes[$taxonomy]['terms'])) :
|
||||
$class = 'class="chosen"';
|
||||
|
||||
// Remove this term is $current_filter has more than 1 term filtered
|
||||
|
@ -206,6 +254,7 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
$current_filter_without_this = array_diff($current_filter, array($term->term_id));
|
||||
$link = add_query_arg( $arg, implode(',', $current_filter_without_this), $link );
|
||||
endif;
|
||||
|
||||
else :
|
||||
$link = add_query_arg( $arg, implode(',', $current_filter), $link );
|
||||
endif;
|
||||
|
@ -220,6 +269,11 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
$link = add_query_arg( 'post_type', $_GET['post_type'], $link );
|
||||
endif;
|
||||
|
||||
// Query type Arg
|
||||
if ($query_type=='or' && !( sizeof($current_filter) == 1 && isset( $_chosen_attributes[$taxonomy]['terms'] ) && is_array($_chosen_attributes[$taxonomy]['terms']) && in_array($term->term_id, $_chosen_attributes[$taxonomy]['terms']) )) :
|
||||
$link = add_query_arg( 'query_type_'.strtolower(sanitize_title($instance['attribute'])), 'or', $link );
|
||||
endif;
|
||||
|
||||
echo '<li '.$class.'>';
|
||||
|
||||
if ($count>0 || $option_is_set) echo '<a href="'.$link.'">'; else echo '<span>';
|
||||
|
@ -253,12 +307,15 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
if (!isset($new_instance['title']) || empty($new_instance['title'])) $new_instance['title'] = $woocommerce->attribute_label($new_instance['attribute']);
|
||||
$instance['title'] = strip_tags(stripslashes($new_instance['title']));
|
||||
$instance['attribute'] = stripslashes($new_instance['attribute']);
|
||||
$instance['query_type'] = stripslashes($new_instance['query_type']);
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/** @see WP_Widget->form */
|
||||
function form( $instance ) {
|
||||
global $woocommerce;
|
||||
|
||||
if (!isset($instance['query_type'])) $instance['query_type'] = 'and';
|
||||
?>
|
||||
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'woothemes') ?></label>
|
||||
<input type="text" class="widefat" id="<?php echo esc_attr( $this->get_field_id('title') ); ?>" name="<?php echo esc_attr( $this->get_field_name('title') ); ?>" value="<?php if (isset ( $instance['title'])) {echo esc_attr( $instance['title'] );} ?>" /></p>
|
||||
|
@ -281,7 +338,13 @@ class WooCommerce_Widget_Layered_Nav extends WP_Widget {
|
|||
endforeach;
|
||||
endif;
|
||||
?>
|
||||
</select>
|
||||
</select></p>
|
||||
|
||||
<p><label for="<?php echo $this->get_field_id('query_type'); ?>"><?php _e('Query Type:', 'woothemes') ?></label>
|
||||
<select id="<?php echo esc_attr( $this->get_field_id('query_type') ); ?>" name="<?php echo esc_attr( $this->get_field_name('query_type') ); ?>">
|
||||
<option value="and" <?php selected($instance['query_type'], 'and'); ?>><?php _e('AND', 'woothemes'); ?></option>
|
||||
<option value="or" <?php selected($instance['query_type'], 'or'); ?>><?php _e('OR', 'woothemes'); ?></option>
|
||||
</select></p>
|
||||
<?php
|
||||
}
|
||||
} // class WooCommerce_Widget_Layered_Nav
|
|
@ -105,10 +105,10 @@ class WooCommerce_Widget_Price_Filter extends WP_Widget {
|
|||
function widget( $args, $instance ) {
|
||||
extract($args);
|
||||
|
||||
if (!is_tax( 'product_cat' ) && !is_post_type_archive('product') && !is_tax( 'product_tag' )) return;
|
||||
|
||||
global $_chosen_attributes, $wpdb, $woocommerce, $wp_query;
|
||||
|
||||
if (!is_tax( 'product_cat' ) && !is_post_type_archive('product') && !is_tax( 'product_tag' )) return;
|
||||
|
||||
$title = $instance['title'];
|
||||
$title = apply_filters('widget_title', $title, $instance, $this->id_base);
|
||||
|
||||
|
@ -120,24 +120,36 @@ class WooCommerce_Widget_Price_Filter extends WP_Widget {
|
|||
if (get_search_query()) $fields = '<input type="hidden" name="s" value="'.get_search_query().'" />';
|
||||
if (isset($_GET['post_type'])) $fields .= '<input type="hidden" name="post_type" value="'.esc_attr( $_GET['post_type'] ).'" />';
|
||||
|
||||
if ($_chosen_attributes) foreach ($_chosen_attributes as $attribute => $value) :
|
||||
if ($_chosen_attributes) foreach ($_chosen_attributes as $attribute => $data) :
|
||||
|
||||
$fields .= '<input type="hidden" name="'.esc_attr( str_replace('pa_', 'filter_', $attribute) ).'" value="'.esc_attr( implode(',', $value) ).'" />';
|
||||
$fields .= '<input type="hidden" name="'.esc_attr( str_replace('pa_', 'filter_', $attribute) ).'" value="'.esc_attr( implode(',', $data['terms']) ).'" />';
|
||||
if ($data['query_type']=='or') $fields .= '<input type="hidden" name="'.esc_attr( str_replace('pa_', 'query_type_', $attribute) ).'" value="or" />';
|
||||
|
||||
endforeach;
|
||||
|
||||
$min = 0;
|
||||
|
||||
if (sizeof($woocommerce->query->layered_nav_product_ids)==0) :
|
||||
|
||||
$max = ceil($wpdb->get_var("SELECT max(meta_value + 0)
|
||||
FROM $wpdb->posts
|
||||
LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id
|
||||
WHERE meta_key = 'price' AND (
|
||||
$wpdb->posts.ID IN (".implode(',', $woocommerce->query->layered_nav_product_ids).")
|
||||
OR (
|
||||
$wpdb->posts.post_parent IN (".implode(',', $woocommerce->query->layered_nav_product_ids).")
|
||||
AND $wpdb->posts.post_parent != 0
|
||||
)
|
||||
)"));
|
||||
$max = ceil($wpdb->get_var("SELECT max(meta_value + 0)
|
||||
FROM $wpdb->posts
|
||||
LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id
|
||||
WHERE meta_key = 'price'"));
|
||||
|
||||
else :
|
||||
|
||||
$max = ceil($wpdb->get_var("SELECT max(meta_value + 0)
|
||||
FROM $wpdb->posts
|
||||
LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id
|
||||
WHERE meta_key = 'price' AND (
|
||||
$wpdb->posts.ID IN (".implode(',', $woocommerce->query->layered_nav_product_ids).")
|
||||
OR (
|
||||
$wpdb->posts.post_parent IN (".implode(',', $woocommerce->query->layered_nav_product_ids).")
|
||||
AND $wpdb->posts.post_parent != 0
|
||||
)
|
||||
)"));
|
||||
|
||||
endif;
|
||||
|
||||
echo '<form method="get" action="">
|
||||
<div class="price_slider_wrapper">
|
||||
|
|
Loading…
Reference in New Issue