Advanced AJAX Product Filters - Version 1.0.4.6

Version Description

  • Fix - database query issue that brake plugin in categories
Download this release

Release Info

Developer dholovnia
Plugin Icon wp plugin Advanced AJAX Product Filters
Version 1.0.4.6
Comparing to
See all releases

Code changes from version 1.0.4.4 to 1.0.4.6

includes/widget.php CHANGED
@@ -74,7 +74,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
74
 
75
  if( ! $br_options['products_holder_id'] ) $br_options['products_holder_id'] = 'ul.products';
76
 
77
- if( $_POST['terms'] ){
78
  $post_temrs = @ json_encode( $_POST['terms'] );
79
  }else{
80
  $post_temrs = "[]";
@@ -91,7 +91,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
91
  'control_sorting' => $br_options['control_sorting'],
92
  'seo_friendly_urls' => $br_options['seo_friendly_urls'],
93
  'berocket_aapf_widget_product_filters' => $post_temrs,
94
- 'user_func' => $br_options['user_func'],
95
  )
96
  );
97
 
@@ -137,21 +137,18 @@ class BeRocket_AAPF_Widget extends WP_Widget {
137
  $price_range = BeRocket_AAPF_Widget::get_price_range( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
138
  if( ! $price_range ) return false;
139
  }else{
140
- $my_query = BeRocket_AAPF_Widget::get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
141
-
142
- if ( $my_query->have_posts() ) {
143
- while ( $my_query->have_posts() ) {
144
- $my_query->the_post();
145
- $t_terms = get_the_terms( $my_query->post->ID, $attribute );
146
- if( $t_terms ) {
147
- foreach ( $t_terms as $key => $val ) {
148
- $terms[ $key ] = $val;
149
- $sort_terms[ $key ] = $val->name;
150
- }
151
  }
152
  }
153
  }
154
-
155
  if ( @ count( $terms ) < 2 ) return false;
156
 
157
  array_multisort( $sort_terms, $terms );
@@ -215,11 +212,11 @@ class BeRocket_AAPF_Widget extends WP_Widget {
215
  $slider_value1 = $min;
216
  $slider_value2 = $max;
217
 
218
- if( $attribute == 'price' and $_POST['price'] ){
219
  $slider_value1 = $_POST['price'][0];
220
  $slider_value2 = $_POST['price'][1];
221
  }
222
- if( $attribute != 'price' and $_POST['limits'] ){
223
  foreach( $_POST['limits'] as $p_limit ){
224
  if( $p_limit[0] == $attribute ){
225
  $slider_value1 = $p_limit[1];
@@ -256,17 +253,14 @@ class BeRocket_AAPF_Widget extends WP_Widget {
256
 
257
  public static function get_price_range( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items ){
258
  $price_range = array();
259
- $my_query = BeRocket_AAPF_Widget::get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
260
-
261
- if ( $my_query->have_posts() ) {
262
- while ( $my_query->have_posts() ) {
263
- $my_query->the_post();
264
- $meta_values = get_post_meta( $my_query->post->ID, '_price' );
265
- if ( $meta_values[0] or $woocommerce_hide_out_of_stock_items != 'yes' ) {
266
- $price_range[] = $meta_values[0];
267
- }
268
- }
269
- }
270
 
271
  if ( @ count( $price_range ) < 2 ) {
272
  $price_range = false;
@@ -275,38 +269,43 @@ class BeRocket_AAPF_Widget extends WP_Widget {
275
  return apply_filters( 'berocket_aapf_get_price_range', $price_range );
276
  }
277
 
278
- function get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items ) {
279
- $args = array(
280
- 'post_type' => 'product',
281
- 'orderby' => 'category',
282
- 'order' => 'ASC',
283
- 'ignore_sticky_posts' => 1
284
- );
285
 
286
  if ( $wp_query_product_cat != - 1 ) {
287
- $args['tax_query'] = array(
288
- array(
289
- 'taxonomy' => 'product_cat',
290
- 'field' => 'slug',
291
- 'terms' => array( $wp_query_product_cat ),
292
- )
293
- );
294
  }
295
 
296
  if ( $woocommerce_hide_out_of_stock_items == 'yes' ) {
297
- $args['meta_query'] = array(
298
- array(
299
- 'key' => '_stock_status',
300
- 'value' => 'instock',
301
- 'compare' => '='
302
- )
303
- );
304
  }
305
 
306
- $args = apply_filters( 'berocket_aapf_get_filter_products_args', $args );
307
-
308
- return new WP_Query( $args );
 
 
 
 
 
 
 
 
 
309
  }
 
310
  /**
311
  * Validating and updating widget data
312
  *
@@ -382,7 +381,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
382
  add_filter( 'post_class', array( __CLASS__, 'add_product_class' ) );
383
  add_filter( 'woocommerce_pagination_args', array( __CLASS__, 'pagination_args' ) );
384
 
385
- $args = apply_filters( 'berocket_aapf_listener_wp_query_args', $args );
386
 
387
  $args['post__in'] = BeRocket_AAPF::limits_filter( array() );
388
  $args['post__in'] = BeRocket_AAPF::price_filter( $args['post__in'] );
74
 
75
  if( ! $br_options['products_holder_id'] ) $br_options['products_holder_id'] = 'ul.products';
76
 
77
+ if( @ $_POST['terms'] ){
78
  $post_temrs = @ json_encode( $_POST['terms'] );
79
  }else{
80
  $post_temrs = "[]";
91
  'control_sorting' => $br_options['control_sorting'],
92
  'seo_friendly_urls' => $br_options['seo_friendly_urls'],
93
  'berocket_aapf_widget_product_filters' => $post_temrs,
94
+ 'user_func' => @ $br_options['user_func'],
95
  )
96
  );
97
 
137
  $price_range = BeRocket_AAPF_Widget::get_price_range( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
138
  if( ! $price_range ) return false;
139
  }else{
140
+ $products = BeRocket_AAPF_Widget::get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
141
+
142
+ foreach ( $products as $product ) {
143
+ $t_terms = get_the_terms( $product->ID, $attribute );
144
+ if( $t_terms ) {
145
+ foreach ( $t_terms as $val ) {
146
+ $terms[ $val->term_id ] = $val;
147
+ $sort_terms[ $val->term_id ] = $val->name;
 
 
 
148
  }
149
  }
150
  }
151
+
152
  if ( @ count( $terms ) < 2 ) return false;
153
 
154
  array_multisort( $sort_terms, $terms );
212
  $slider_value1 = $min;
213
  $slider_value2 = $max;
214
 
215
+ if( $attribute == 'price' and @ $_POST['price'] ){
216
  $slider_value1 = $_POST['price'][0];
217
  $slider_value2 = $_POST['price'][1];
218
  }
219
+ if( $attribute != 'price' and @ $_POST['limits'] ){
220
  foreach( $_POST['limits'] as $p_limit ){
221
  if( $p_limit[0] == $attribute ){
222
  $slider_value1 = $p_limit[1];
253
 
254
  public static function get_price_range( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items ){
255
  $price_range = array();
256
+ $products = BeRocket_AAPF_Widget::get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items );
257
+
258
+ foreach ( $products as $product ) {
259
+ $meta_values = get_post_meta( $product->ID, '_price' );
260
+ if ( $meta_values[0] or $woocommerce_hide_out_of_stock_items != 'yes' ) {
261
+ $price_range[] = $meta_values[0];
262
+ }
263
+ }
 
 
 
264
 
265
  if ( @ count( $price_range ) < 2 ) {
266
  $price_range = false;
269
  return apply_filters( 'berocket_aapf_get_price_range', $price_range );
270
  }
271
 
272
+ public static function get_filter_products( $wp_query_product_cat, $woocommerce_hide_out_of_stock_items ) {
273
+ global $wpdb;
274
+
275
+ $from = $group = '';
276
+ $where = " AND ({$wpdb->posts}.post_status = 'publish') ";
 
 
277
 
278
  if ( $wp_query_product_cat != - 1 ) {
279
+ $wp_query_product_cat = get_term_by( 'slug', $wp_query_product_cat, 'product_cat', OBJECT );
280
+ $wp_query_product_cat_id = $wp_query_product_cat->term_id;
281
+
282
+ $from = " INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id) ";
283
+ $where = " AND ( {$wpdb->term_relationships}.term_taxonomy_id IN ( {$wp_query_product_cat_id} ) )
284
+ AND ({$wpdb->posts}.post_status = 'publish' OR {$wpdb->posts}.post_status = 'private') ";
285
+ $group = " GROUP BY {$wpdb->posts}.ID ";
286
  }
287
 
288
  if ( $woocommerce_hide_out_of_stock_items == 'yes' ) {
289
+ $from .= " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id) ";
290
+ $where .= " AND ({$wpdb->posts}.post_status = 'publish' OR {$wpdb->posts}.post_status = 'private')
291
+ AND ( ({$wpdb->postmeta}.meta_key = '_stock_status' AND CAST({$wpdb->postmeta}.meta_value AS CHAR) = 'instock') ) ";
292
+ $group = " GROUP BY {$wpdb->posts}.ID ";
 
 
 
293
  }
294
 
295
+ $results = $wpdb->get_results("
296
+ SELECT SQL_CALC_FOUND_ROWS {$wpdb->posts}.ID
297
+ FROM {$wpdb->posts}
298
+ {$from}
299
+ WHERE 1=1
300
+ AND {$wpdb->posts}.post_type = 'product'
301
+ {$where}
302
+ {$group}
303
+ ORDER BY {$wpdb->posts}.post_date ASC"
304
+ , OBJECT );
305
+
306
+ return $results;
307
  }
308
+
309
  /**
310
  * Validating and updating widget data
311
  *
381
  add_filter( 'post_class', array( __CLASS__, 'add_product_class' ) );
382
  add_filter( 'woocommerce_pagination_args', array( __CLASS__, 'pagination_args' ) );
383
 
384
+ $args = apply_filters( 'berocket_aapf_listener_wp_query_args', array() );
385
 
386
  $args['post__in'] = BeRocket_AAPF::limits_filter( array() );
387
  $args['post__in'] = BeRocket_AAPF::price_filter( $args['post__in'] );
js/widget.min.js CHANGED
@@ -1,2 +1,297 @@
1
  /* http://dean.edwards.name/packer/ */
2
- eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(6($){$(18).1U(6(){19 d=1V.1W(5.1X),J=[],S=[],T=1;4($(\'.7-n\').B(\'.7-n\')){T=u($(\'.7-n .C\').U());4(T<1)T=1}6 K(b){4(v 5.g!=\'w\'&&5.g!=1a&&v 5.g.1b!=\'w\'&&5.g.1b.h>0){1c(5.g.1b)}$(5.V).1Y(\'1d\').1Z(\'<1r 1s="1t" />\');4(b){4(b.L("D"))p=b.20("1u:1v").e();j p=b.e();4(b.L("D")){$(d).x(6(i,o){4(o[0]==p.M){d.1w(i,1)}});4(b.E())d[d.h]=[p.M,p.1e,p.1x]}j{4(b.L(\':21\')||b.L(\':1v\')){d[d.h]=[p.M,p.1e,p.1x]}j{$(d).x(6(i,o){4(o[0]==p.M&&o[1]==p.1e){d.1w(i,1)}})}}}J=[];S=[];$t=$(\'.W\');4($t.B(\'W\')){$t.x(6(i,o){X=$(\'#\'+$(o).e(\'1y\')).E();Y=$(\'#\'+$(o).e(\'1z\')).E();4(X!=$(o).e(\'Z\')||Y!=$(o).e(\'10\')){4($(o).B(\'1f\')){S=[X,Y]}j{J[J.h]=[$(o).e(\'M\'),X,Y]}}})}4($(\'.7-n\').B(\'.7-n\')){$(\'.7-n 22.y-1A 23 a\')}r={1g:d,s:S,1h:J,N:5.N,24:\'25\',z:$(\'.7-11 D.z\').E()};4(5.26&&\'12\'1B 27&&\'1C\'1B 12){1D(r);r.m=m.F}j{r.m=5.1E;8=$(\'.7-n O.C\').U();4(G=m.F.H(/.+\\/y\\/([0-9]+).+/,"$1")){4(!u(8)){8=G}r.m=r.m.H(/\\/?/,"")+"/y/"+8+"/"}j 4(G=m.F.H(/.+P?=([0-9]+).+/,"$1")){4(!u(8)){8=G}r.m=r.m.H(/\\/?/,"")+"?y="+8+""}}$.28(5.29,r,6(a){$(\'.7-2a-2b\').Q();$(\'.7-n\').Q();$(\'1F.7-11\').Q();4(v 5.g!=\'w\'&&5.g!=1a&&v 5.g.1i!=\'w\'&&5.g.1i.h>0){1c(5.g.1i)}4($(\'.7-1j\').B(\'7-1j\')&&!$(5.V).L(\':2c\')){4(v a.1k!=\'w\'){$(\'.7-1j\').1G(a.1k)}}j{4(v a.1H!=\'w\'){$(5.V).2d(a.1H).1l(\'1d\')}j{$(5.V).1G(a.1k).1l(\'1d\')}}$(\'.1t\').Q();1m();4(v 5.g!=\'w\'&&5.g!=1a&&v 5.g.1n!=\'w\'&&5.g.1n.h>0){1c(5.g.1n)}},"2e")}6 1D(a){l=[];q=\'\';4(a.z&&$(\'.7-11 D.z 1u:2f\').2g(\'2h\')!=a.z){l[l.h]=\'2i=\'+a.z}4(a.N&&a.N>0){l[l.h]=\'2j=\'+a.N}4(a.s){$1o=$(\'.1f\');4(a.s[0]&&a.s[1]&&(a.s[0]!=$1o.e(\'Z\')||a.s[1]!=$1o.e(\'10\'))){l[l.h]=\'s=\'+a.s[0]+\'^\'+a.s[1]}}4(a.1h){$(a.1h).x(6(i,o){l[l.h]=o[0].1I(3)+\'=\'+o[1]+\'^\'+o[2]})}4(a.1g){$(a.1g).x(6(i,o){l[l.h]=o[0].1I(3)+\'=\'+o[1]+\'^\'+o[2]})}19 b=5.1E;4(l.h){$(l).x(6(i,o){4(q)q+="|";q+=o})}8=$(\'.7-n O.C\').U();4(G=u(m.F.H(/.+\\/y\\/([0-9]+).+/,"$1"))){4(!u(8)){8=G}b=b.H(/\\/?$/,"")+"/y/"+8+"/";4(q){b=b+"?13="+q}}j{14=15;4(/\\?/.1J(m.F)){R=m.F.16(\'?\');4(R[1]){f=[];2k=[];4(/&/.1J(R[1])){f=R[1].16(\'&\');1K=f.h;1L(k=0;k<1K;k++){I=f[k].16(\'=\');f[k]=[];f[k][0]=I.1M();f[k][1]=I.1N("=")}}j{f[0]=[];I=R[1].16(\'=\');f[0][0]=I.1M();f[0][1]=I.1N("=")}1L(k=0;k<f.h;k++){4(f[k][0]==\'13\'||f[k][0]==\'y\'||f[k][0]==\'P\')2l;4(14)b+=\'&\';j b+=\'?\';b+=f[k][0]+\'=\'+f[k][1];14=1O}}}4(14&&q){b=b+"&13="+q;4(8>1){b=b+"&P="+u(8)}}j 4(q){b=b+"?13="+q;4(8>1){b=b+"&P="+u(8)}}j 4(8>1){b=b+"?P="+u(8)}}19 c={1P:"1Q"};12.1C(c,"1P 1Q",b);12.2m=b}6 1m(){$(\'.7-n\').17(\'2n\',\'a\',6(a){a.1p();$(\'.7-n O.C\').1l(\'C\');$(1q).2o("<O 1s=\'y-1A C\'>"+$(1q).U()+"</O>").Q();K(15)})}$(\'.2p\').17("1R","2q, D",6(){K($(1q))});$(".W").x(6(i,o){$(o).2r({2s:1O,Z:$(o).e(\'Z\')>>0,10:$(o).e(\'10\')>>0,1S:[$(o).e(\'2t\')>>0,$(o).e(\'2u\')>>0],2v:6(a,b){$o=$(b.2w).2x(\'1r.W\');A=b.1S;4($(o).B(\'1f\')){A[0]=A[0].1T(2);A[1]=A[1].1T(2)}$(\'#\'+$o.e(\'1y\')).E(A[0]);$(\'#\'+$o.e(\'1z\')).E(A[1])},2y:6(){K(15)}})});$(".2z").x(6(i,o){$(o).2A({2B:"2C",2D:$(o).e(\'2E\'),2F:2G})});4(5.2H){$(18).17(\'2I\',\'1F.7-11\',6(a){a.1p()});$(18).17(\'1R\',\'D.z\',6(a){a.1p();K(15)})}1m()})})(2J);',62,170,'||||if|the_ajax_script|function|woocommerce|cur_page||||||data|passed_vars2|user_func|length||else||uri_request_array|location|pagination||el_data|uri_request|args|price||parseInt|typeof|undefined|each|page|orderby|vals|hasClass|current|select|val|href|prev_page|replace|temp|berocket_aapf_widget_product_limits|updateProducts|is|taxonomy|product_cat|span|paged|remove|passed_vars1|berocket_aapf_widget_product_price_limit|woocommerce_pagination_page|text|products_holder_id|berocket_filter_slider|val1|val2|min|max|ordering|history|filters|something_added|false|split|on|document|var|null|before_update|eval|hide_products|term_id|berocket_filter_price_slider|terms|limits|on_update|info|products|removeClass|aapf_action_init|after_update|price_obj|preventDefault|this|div|class|berocket_aapf_widget_loading|option|selected|splice|operator|fields_1|fields_2|numbers|in|pushState|updateLocation|current_page_url|form|replaceWith|no_products|substring|test|passed_vars2_length|for|shift|join|true|BeRocket|Rules|change|values|toFixed|ready|JSON|parse|berocket_aapf_widget_product_filters|addClass|append|find|checked|ul|li|action|berocket_aapf_listener|seo_friendly_urls|window|post|ajaxurl|result|count|visible|html|json|first|attr|value|order|pcategory|temp2|continue|pathname|click|after|berocket_aapf_widget|input|slider|range|value1|value2|slide|handle|parents|stop|berocket_aapf_widget_height_control|mCustomScrollbar|axis|xy|theme|scroll_theme|scrollInertia|300|control_sorting|submit|jQuery'.split('|'),0,{}))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /* http://dean.edwards.name/packer/ */
2
+ (function ($){
3
+ $(document).ready(function (){
4
+
5
+ var berocket_aapf_widget_product_filters = JSON.parse(the_ajax_script.berocket_aapf_widget_product_filters),
6
+ berocket_aapf_widget_product_limits = [],
7
+ berocket_aapf_widget_product_price_limit = [],
8
+ woocommerce_pagination_page = 1;
9
+
10
+ if( $('.woocommerce-pagination').hasClass('.woocommerce-pagination') ){
11
+ woocommerce_pagination_page = parseInt( $('.woocommerce-pagination .current').text() );
12
+ if( woocommerce_pagination_page < 1 ) woocommerce_pagination_page = 1;
13
+ }
14
+
15
+ function updateProducts( $el ){
16
+ if ( typeof the_ajax_script.user_func != 'undefined'
17
+ && the_ajax_script.user_func != null
18
+ && typeof the_ajax_script.user_func.before_update != 'undefined'
19
+ && the_ajax_script.user_func.before_update.length > 0
20
+ ) {
21
+ eval( the_ajax_script.user_func.before_update );
22
+ }
23
+
24
+ $(the_ajax_script.products_holder_id).addClass('hide_products').append('<div class="berocket_aapf_widget_loading" />');
25
+
26
+ if( $el ){
27
+ if( $el.is("select") ) el_data = $el.find("option:selected").data();
28
+ else el_data = $el.data();
29
+
30
+ if( $el.is("select") ){
31
+ $(berocket_aapf_widget_product_filters).each(function (i, o) {
32
+ if (o[0] == el_data.taxonomy) {
33
+ berocket_aapf_widget_product_filters.splice(i, 1);
34
+ }
35
+ });
36
+ if( $el.val() )
37
+ berocket_aapf_widget_product_filters[berocket_aapf_widget_product_filters.length] = [el_data.taxonomy, el_data.term_id, el_data.operator];
38
+ }else {
39
+ if ($el.is(':checked') || $el.is(':selected')) {
40
+ berocket_aapf_widget_product_filters[berocket_aapf_widget_product_filters.length] = [el_data.taxonomy, el_data.term_id, el_data.operator];
41
+ } else {
42
+ $(berocket_aapf_widget_product_filters).each(function (i, o) {
43
+ if (o[0] == el_data.taxonomy && o[1] == el_data.term_id) {
44
+ berocket_aapf_widget_product_filters.splice(i, 1);
45
+ }
46
+ });
47
+ }
48
+ }
49
+ }
50
+
51
+ berocket_aapf_widget_product_limits = [];
52
+ berocket_aapf_widget_product_price_limit = [];
53
+
54
+ $t = $('.berocket_filter_slider');
55
+ if( $t.hasClass('berocket_filter_slider') ){
56
+ $t.each(function (i,o){
57
+ val1 = $('#'+$(o).data('fields_1')).val();
58
+ val2 = $('#'+$(o).data('fields_2')).val();
59
+ if( val1 != $(o).data('min') || val2 != $(o).data('max') ){
60
+ if( $(o).hasClass('berocket_filter_price_slider') ){
61
+ berocket_aapf_widget_product_price_limit = [val1, val2];
62
+ }else{
63
+ berocket_aapf_widget_product_limits[berocket_aapf_widget_product_limits.length] = [$(o).data('taxonomy'), val1, val2];
64
+ }
65
+ }
66
+ });
67
+ }
68
+
69
+ if( $('.woocommerce-pagination').hasClass( '.woocommerce-pagination' ) ){
70
+ $('.woocommerce-pagination ul.page-numbers li a');
71
+ }
72
+
73
+ args = {
74
+ terms: berocket_aapf_widget_product_filters,
75
+ price: berocket_aapf_widget_product_price_limit,
76
+ limits: berocket_aapf_widget_product_limits,
77
+ product_cat: the_ajax_script.product_cat,
78
+ action: 'berocket_aapf_listener',
79
+ orderby: $('.woocommerce-ordering select.orderby').val()
80
+ };
81
+
82
+ if( the_ajax_script.seo_friendly_urls && 'history' in window && 'pushState' in history ) {
83
+ updateLocation(args);
84
+ args.location = location.href;
85
+ }else{
86
+ args.location = the_ajax_script.current_page_url;
87
+
88
+ cur_page = $('.woocommerce-pagination span.current').text();
89
+ if( prev_page = location.href.replace(/.+\/page\/([0-9]+).+/, "$1") ){
90
+ if( ! parseInt( cur_page ) ){
91
+ cur_page = prev_page;
92
+ }
93
+ args.location = args.location.replace(/\/?/,"") + "/page/" + cur_page + "/";
94
+ }else if( prev_page = location.href.replace(/.+paged?=([0-9]+).+/, "$1") ){
95
+ if( ! parseInt( cur_page ) ){
96
+ cur_page = prev_page;
97
+ }
98
+ args.location = args.location.replace(/\/?/,"") + "?page=" + cur_page + "";
99
+ }
100
+ }
101
+
102
+ $.post(the_ajax_script.ajaxurl, args, function (data) {
103
+ $('.woocommerce-result-count').remove();
104
+ $('.woocommerce-pagination').remove();
105
+ $('form.woocommerce-ordering').remove();
106
+
107
+ if ( typeof the_ajax_script.user_func != 'undefined'
108
+ && the_ajax_script.user_func != null
109
+ && typeof the_ajax_script.user_func.on_update != 'undefined'
110
+ && the_ajax_script.user_func.on_update.length > 0
111
+ ) {
112
+ eval( the_ajax_script.user_func.on_update );
113
+ }
114
+
115
+ if ( $('.woocommerce-info').hasClass('woocommerce-info') && ! $(the_ajax_script.products_holder_id).is(':visible') ) {
116
+ if ( typeof data.products != 'undefined' ) {
117
+ $('.woocommerce-info').replaceWith(data.products);
118
+ }
119
+ } else {
120
+ if ( typeof data.no_products != 'undefined' ) {
121
+ $(the_ajax_script.products_holder_id).html(data.no_products).removeClass('hide_products');
122
+ } else {
123
+ $(the_ajax_script.products_holder_id).replaceWith(data.products).removeClass('hide_products');
124
+ }
125
+ }
126
+
127
+ $('.berocket_aapf_widget_loading').remove();
128
+
129
+ aapf_action_init();
130
+
131
+ if ( typeof the_ajax_script.user_func != 'undefined'
132
+ && the_ajax_script.user_func != null
133
+ && typeof the_ajax_script.user_func.after_update != 'undefined'
134
+ && the_ajax_script.user_func.after_update.length > 0
135
+ ) {
136
+ eval( the_ajax_script.user_func.after_update );
137
+ }
138
+ }, "json");
139
+ }
140
+
141
+ function updateLocation( args ){
142
+ uri_request_array = [];
143
+ uri_request = '';
144
+
145
+ if( args.orderby && $('.woocommerce-ordering select.orderby option:first').attr('value') != args.orderby ){
146
+ uri_request_array[uri_request_array.length] = 'order='+args.orderby;
147
+ }
148
+ if( args.product_cat && args.product_cat > 0 ){
149
+ uri_request_array[uri_request_array.length] = 'pcategory='+args.product_cat;
150
+ }
151
+ if( args.price ){
152
+ $price_obj = $('.berocket_filter_price_slider');
153
+ if( args.price[0] && args.price[1] && ( args.price[0] != $price_obj.data('min') || args.price[1] != $price_obj.data('max') ) ){
154
+ uri_request_array[uri_request_array.length] = 'price='+args.price[0]+'^'+args.price[1];
155
+ }
156
+ }
157
+ if( args.limits ){
158
+ $( args.limits).each(function (i,o){
159
+ uri_request_array[uri_request_array.length] = o[0].substring(3)+'='+o[1]+'^'+o[2];
160
+ });
161
+ }
162
+ if( args.terms ){
163
+ $( args.terms).each(function (i,o){
164
+ uri_request_array[uri_request_array.length] = o[0].substring(3)+'='+o[1]+'^'+o[2];
165
+ });
166
+ }
167
+
168
+ var uri = the_ajax_script.current_page_url;
169
+
170
+ if( uri_request_array.length ){
171
+ $(uri_request_array).each(function (i,o){
172
+ if( uri_request ) uri_request += "|";
173
+ uri_request += o;
174
+ });
175
+ }
176
+
177
+ cur_page = $('.woocommerce-pagination span.current').text();
178
+ if( prev_page = parseInt( location.href.replace(/.+\/page\/([0-9]+).+/, "$1") ) ){
179
+ if( ! parseInt( cur_page ) ){
180
+ cur_page = prev_page;
181
+ }
182
+ uri = uri.replace(/\/?$/,"") + "/page/" + cur_page + "/";
183
+ if( uri_request ){
184
+ uri = uri + "?filters=" + uri_request;
185
+ }
186
+ }else{
187
+ something_added = false;
188
+ if( /\?/.test(location.href) ){
189
+ passed_vars1 = location.href.split('?');
190
+ if( passed_vars1[1] ){
191
+ passed_vars2 = [];
192
+ temp2 = [];
193
+ if( /&/.test(passed_vars1[1]) ) {
194
+ passed_vars2 = passed_vars1[1].split('&');
195
+ passed_vars2_length = passed_vars2.length;
196
+ for ( k = 0; k < passed_vars2_length; k++ ){
197
+ temp = passed_vars2[k].split('=');
198
+ passed_vars2[k] = [];
199
+ passed_vars2[k][0] = temp.shift();
200
+ passed_vars2[k][1] = temp.join("=")
201
+ }
202
+ }else{
203
+ passed_vars2[0] = [];
204
+ temp = passed_vars1[1].split('=');
205
+ passed_vars2[0][0] = temp.shift();
206
+ passed_vars2[0][1] = temp.join("=")
207
+ }
208
+ for ( k = 0; k < passed_vars2.length; k++ ){
209
+ if( passed_vars2[k][0] == 'filters' || passed_vars2[k][0] == 'page' || passed_vars2[k][0] == 'paged' ) continue;
210
+
211
+ if( something_added ) uri += '&';
212
+ else uri += '?';
213
+
214
+ uri += passed_vars2[k][0]+'='+passed_vars2[k][1];
215
+ something_added = true;
216
+ }
217
+ }
218
+ }
219
+ if( something_added && uri_request ){
220
+ uri = uri + "&filters=" + uri_request;
221
+ if( cur_page > 1 ){
222
+ uri = uri + "&paged=" + parseInt( cur_page );
223
+ }
224
+ }else if( uri_request ){
225
+ uri = uri + "?filters=" + uri_request;
226
+ if( cur_page > 1 ){
227
+ uri = uri + "&paged=" + parseInt( cur_page );
228
+ }
229
+ }else if( cur_page > 1 ){
230
+ uri = uri + "?paged=" + parseInt( cur_page );
231
+ }
232
+ }
233
+
234
+ var stateParameters = { BeRocket: "Rules" };
235
+ history.pushState(stateParameters, "BeRocket Rules", uri);
236
+ history.pathname = uri;
237
+ }
238
+
239
+ function aapf_action_init(){
240
+ // Take control over (default) pagination and sorting, make it AJAXy and work with filters
241
+ $('.woocommerce-pagination').on('click', 'a', function (event) {
242
+ event.preventDefault();
243
+ $('.woocommerce-pagination span.current').removeClass('current');
244
+ $(this).after("<span class='page-numbers current'>"+$(this).text()+"</span>").remove();
245
+ updateProducts(false);
246
+ });
247
+ }
248
+
249
+ $('.berocket_aapf_widget').on("change", "input, select", function(){
250
+ updateProducts( $(this) );
251
+ });
252
+
253
+ $( ".berocket_filter_slider" ).each(function (i,o){
254
+ $(o).slider({
255
+ range: true,
256
+ min: $(o).data('min')>>0,
257
+ max: $(o).data('max')>>0,
258
+ values: [$(o).data('value1')>>0,$(o).data('value2')>>0],
259
+ slide: function( event, ui ) {
260
+ $o = $(ui.handle).parents('div.berocket_filter_slider');
261
+ vals = ui.values;
262
+ if( $(o).hasClass('berocket_filter_price_slider') ){
263
+ vals[0] = vals[0].toFixed(2);
264
+ vals[1] = vals[1].toFixed(2);
265
+ }
266
+ $( '#'+$o.data('fields_1') ).val( vals[0] );
267
+ $( '#'+$o.data('fields_2') ).val( vals[1] );
268
+ },
269
+ stop: function(){
270
+ updateProducts( false );
271
+ }
272
+ });
273
+ });
274
+
275
+ $(".berocket_aapf_widget_height_control").each(function (i,o){
276
+ $(o).mCustomScrollbar({
277
+ axis: "xy",
278
+ theme: $(o).data('scroll_theme'),
279
+ scrollInertia: 300
280
+ });
281
+ });
282
+
283
+ // Option to take control over (default) sorting, make it AJAXy and work with filters
284
+ if( the_ajax_script.control_sorting ) {
285
+ $(document).on('submit', 'form.woocommerce-ordering', function (event) {
286
+ event.preventDefault();
287
+ });
288
+ $(document).on('change', 'select.orderby', function (event) {
289
+ event.preventDefault();
290
+ updateProducts(false);
291
+ });
292
+ }
293
+
294
+ aapf_action_init();
295
+
296
+ });
297
+ })(jQuery);
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: http://berocket.com
5
  Tags: filters, product filters, ajax product filters, advanced product filters, woocommerce filters, woocommerce product filters, woocommerce ajax product filters
6
  Requires at least: 3.9
7
  Tested up to: 4.1
8
- Stable tag: 1.0.4.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -78,7 +78,7 @@ http://woocommerce-product-filter.berocket.com
78
  how it looks depends on the theme you choose.
79
 
80
 
81
- = Advanced Settings (Plugin Settings): =
82
  * Plugin settings can be found in admin area, WooCommerce -> Product Filters
83
  * "No Products" message - Text that will be shown if no products found
84
  * "No Products" class - Add class and use it to style "No Products" box
@@ -86,7 +86,7 @@ http://woocommerce-product-filter.berocket.com
86
  * Sorting control - Take control over WooCommerce's sorting selectbox
87
  * SEO friendly urls - url will be changed when filter is selected/changed
88
  * Turn all filters off - If you want to hide filters without losing current configuration just turn them off
89
-
90
 
91
 
92
  == Installation ==
@@ -105,6 +105,13 @@ http://woocommerce-product-filter.berocket.com
105
 
106
  == Changelog ==
107
 
 
 
 
 
 
 
 
108
  = 1.0.4.4 =
109
  * Enhancement - adding callback for before_update, on_update, after_update events.
110
  * Other small fixes
5
  Tags: filters, product filters, ajax product filters, advanced product filters, woocommerce filters, woocommerce product filters, woocommerce ajax product filters
6
  Requires at least: 3.9
7
  Tested up to: 4.1
8
+ Stable tag: 1.0.4.6
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
78
  how it looks depends on the theme you choose.
79
 
80
 
81
+ = Plugin Settings: =
82
  * Plugin settings can be found in admin area, WooCommerce -> Product Filters
83
  * "No Products" message - Text that will be shown if no products found
84
  * "No Products" class - Add class and use it to style "No Products" box
86
  * Sorting control - Take control over WooCommerce's sorting selectbox
87
  * SEO friendly urls - url will be changed when filter is selected/changed
88
  * Turn all filters off - If you want to hide filters without losing current configuration just turn them off
89
+ * JavaScript callback functions: Before, On and After Update. Use it for better implementation into custom/specific theme
90
 
91
 
92
  == Installation ==
105
 
106
  == Changelog ==
107
 
108
+ = 1.0.4.6 =
109
+ * Fix - database query issue that brake plugin in categories
110
+
111
+ = 1.0.4.5 =
112
+ * Fix - attribute values from products on 2+ page wasn't used
113
+ * Fix - not all attributes in use because of array key duplication issue
114
+
115
  = 1.0.4.4 =
116
  * Enhancement - adding callback for before_update, on_update, after_update events.
117
  * Other small fixes
templates/checkbox.php CHANGED
@@ -15,7 +15,7 @@
15
  <input type='checkbox' id='radio_<?=$term->term_id?>'
16
  data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
17
  <?php
18
- if( $_POST['terms'] ){
19
  foreach( $_POST['terms'] as $p_term ){
20
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
21
  echo ' checked="checked"';
15
  <input type='checkbox' id='radio_<?=$term->term_id?>'
16
  data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
17
  <?php
18
+ if( @ $_POST['terms'] ){
19
  foreach( $_POST['terms'] as $p_term ){
20
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
21
  echo ' checked="checked"';
templates/radio.php CHANGED
@@ -4,7 +4,7 @@
4
  <input type='radio' id='radio_<?=$term->term_id?>' name='radio_<?=$term->taxonomy?>_<?=$x?>'
5
  data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
6
  <?php
7
- if( $_POST['terms'] ){
8
  foreach( $_POST['terms'] as $p_term ){
9
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
10
  echo ' checked="checked"';
4
  <input type='radio' id='radio_<?=$term->term_id?>' name='radio_<?=$term->taxonomy?>_<?=$x?>'
5
  data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
6
  <?php
7
+ if( @ $_POST['terms'] ){
8
  foreach( $_POST['terms'] as $p_term ){
9
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
10
  echo ' checked="checked"';
templates/select.php CHANGED
@@ -5,7 +5,7 @@
5
  <?php foreach( $terms as $term ): ?>
6
  <option data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
7
  <?php
8
- if( $_POST['terms'] ){
9
  foreach( $_POST['terms'] as $p_term ){
10
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
11
  echo ' selected="selected"';
5
  <?php foreach( $terms as $term ): ?>
6
  <option data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'
7
  <?php
8
+ if( @ $_POST['terms'] ){
9
  foreach( $_POST['terms'] as $p_term ){
10
  if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
11
  echo ' selected="selected"';
woocommerce-filters.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Advanced AJAX Product Filters for WooCommerce
4
  Plugin URI: http://berocket.com/wp-plugins/product-filters
5
  Description: Advanced AJAX Product Filters for WooCommerce
6
- Version: 1.0.4.4
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
@@ -19,34 +19,34 @@ require_once dirname( __FILE__ ).'/includes/functions.php';
19
 
20
  class BeRocket_AAPF {
21
 
22
- public static $defaults = array(
23
- "no_products_message" => "There are no products meeting your criteria",
24
- "no_products_class" => "",
25
- "control_sorting" => "0",
26
- "products_holder_id" => "ul.products",
27
- "filters_turn_off" => "0",
28
- "seo_friendly_urls" => "0"
29
- );
30
 
31
- function __construct(){
32
- register_activation_hook(__FILE__, array( __CLASS__, 'br_add_defaults' ) );
33
- register_uninstall_hook(__FILE__, array( __CLASS__, 'br_delete_plugin_options' ) );
34
 
35
- add_action( 'admin_menu', array( __CLASS__, 'br_add_options_page' ) );
36
- add_action( 'admin_init', array( __CLASS__, 'register_br_options' ) );
37
 
38
  add_shortcode( 'br_filters', array( __CLASS__, 'shortcode' ) );
39
 
40
  if( @ $_GET['filters'] and ! @ defined( 'DOING_AJAX' ) ) {
41
- add_filter( 'pre_get_posts', array( __CLASS__, 'apply_user_filters' ) );
42
- }
43
- }
44
 
45
- public static function br_add_options_page(){
46
- add_submenu_page( 'woocommerce', 'Product Filters Settings', 'Product Filters', 'manage_options', 'br-product-filters', array( __CLASS__, 'br_render_form' ) );
47
- }
48
 
49
- public static function shortcode( $atts = array() ){
50
  $a = shortcode_atts(
51
  array(
52
  'attribute' => '',
@@ -60,50 +60,51 @@ class BeRocket_AAPF {
60
  ), $atts );
61
  if ( ! $a['attribute'] || ! $a['type'] ) return false;
62
 
63
- BeRocket_AAPF_Widget::widget( array(), $a );
64
- }
 
65
 
66
- public static function br_render_form(){
67
- include AAPF_TEMPLATE_PATH . "admin-settings.php";
68
- }
69
 
70
- public static function apply_user_filters( $query ){
71
  if( $query->is_main_query() and
72
- ( $query->get( 'post_type' ) == 'product' or $query->get( 'product_cat' ) )
73
- or
74
- $query->is_page() && 'page' == get_option( 'show_on_front' ) && $query->get('page_id') == wc_get_page_id('shop')
75
- ){
76
  br_aapf_args_converter();
77
- $args = br_aapf_args_parser();
78
 
79
  if( @ $_POST['price'] ){
80
- list( $_GET['min_price'], $_GET['max_price'] ) = $_POST['price'];
81
- add_filter( 'loop_shop_post_in', array( 'WC_QUERY', 'price_filter' ) );
82
- }
83
 
84
- if ( @ $_POST['limits'] ) {
85
- add_filter( 'loop_shop_post_in', array( __CLASS__, 'limits_filter' ) );
86
- }
87
 
88
- $args_fields = array( 'meta_key', 'tax_query', 'fields', 'where', 'join', 'meta_query' );
89
- foreach( $args_fields as $args_field ){
90
- if( @ $args[$args_field] ){
91
- $query->set( $args_field, $args[$args_field] );
92
- }
93
- }
94
- }
95
 
96
- return $query;
97
- }
98
 
99
- public static function limits_filter( $filtered_posts ){
100
- global $wpdb;
101
 
102
- if ( $_POST['limits'] ) {
103
- $matched_products = array( 0 );
104
 
105
- foreach ( $_POST['limits'] as $v ) {
106
- $matched_products_query = $wpdb->get_results( $wpdb->prepare("
107
  SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
108
  INNER JOIN $wpdb->term_relationships as tr ON ID = tr.object_id
109
  INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
@@ -112,108 +113,108 @@ class BeRocket_AAPF {
112
  AND tt.taxonomy = %s AND t.slug BETWEEN %d AND %d
113
  ", $v[0], $v[1], $v[2] ), OBJECT_K );
114
 
115
- if ( $matched_products_query ) {
116
- foreach ( $matched_products_query as $product ) {
117
- if ( $product->post_type == 'product' )
118
- $matched_products[] = $product->ID;
119
- if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
120
- $matched_products[] = $product->post_parent;
121
- }
122
- }
123
- }
124
-
125
- $matched_products = array_unique( $matched_products );
126
-
127
- // Filter the id's
128
- if ( sizeof( $filtered_posts ) == 0) {
129
- $filtered_posts = $matched_products;
130
- } else {
131
- $filtered_posts = array_intersect( $filtered_posts, $matched_products );
132
- }
133
- }
134
-
135
- return (array) $filtered_posts;
136
- }
137
-
138
- public static function price_filter( $filtered_posts ){
139
- global $wpdb;
140
-
141
- if ( $_POST['price'] ) {
142
- $matched_products = array( 0 );
143
- $min = floatval( $_POST['price'][0] );
144
- $max = floatval( $_POST['price'][1] );
145
-
146
- $matched_products_query = apply_filters( 'woocommerce_price_filter_results', $wpdb->get_results( $wpdb->prepare("
147
  SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
148
  INNER JOIN $wpdb->postmeta ON ID = post_id
149
  WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish' AND meta_key = %s AND meta_value BETWEEN %d AND %d
150
  ", '_price', $min, $max ), OBJECT_K ), $min, $max );
151
 
152
- if ( $matched_products_query ) {
153
- foreach ( $matched_products_query as $product ) {
154
- if ( $product->post_type == 'product' )
155
- $matched_products[] = $product->ID;
156
- if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
157
- $matched_products[] = $product->post_parent;
158
- }
159
- }
160
-
161
- // Filter the id's
162
- if ( sizeof( $filtered_posts ) == 0) {
163
- $filtered_posts = $matched_products;
164
- } else {
165
- $filtered_posts = array_intersect( $filtered_posts, $matched_products );
166
- }
167
-
168
- }
169
-
170
- return (array) $filtered_posts;
171
- }
172
-
173
- /**
174
- * Get template part (for templates like the slider).
175
- *
176
- * @access public
177
- * @param string $name (default: '')
178
- * @return void
179
- */
180
- public static function br_get_template_part( $name = '' ) {
181
- $template = '';
182
-
183
- // Look in your_child_theme/woocommerce-filters/name.php
184
- if ( $name ) {
185
- $template = locate_template( "woocommerce-filters/{$name}.php" );
186
- }
187
-
188
- // Get default slug-name.php
189
- if ( ! $template && $name && file_exists( AAPF_TEMPLATE_PATH . "{$name}.php" ) ) {
190
- $template = AAPF_TEMPLATE_PATH . "{$name}.php";
191
- }
192
-
193
- // Allow 3rd party plugin filter template file from their plugin
194
- $template = apply_filters( 'br_get_template_part', $template, $name );
195
-
196
-
197
- if ( $template ) {
198
- load_template( $template, false );
199
- }
200
- }
201
-
202
- public static function register_br_options() {
203
- register_setting( 'br_filters_plugin_options', 'br_filters_options' );
204
- }
205
-
206
- public static function br_add_defaults(){
207
- $tmp = get_option('br_filters_options');
208
- if( @$tmp['chk_default_options_db'] == '1' or ! @is_array( $tmp ) ){
209
- delete_option( 'br_filters_options' );
210
- update_option( 'br_filters_options', BeRocket_AAPF::$defaults );
211
- }
212
- }
213
-
214
- public static function br_delete_plugin_options(){
215
- delete_option( 'br_filters_options' );
216
- }
217
 
218
  }
219
 
3
  Plugin Name: Advanced AJAX Product Filters for WooCommerce
4
  Plugin URI: http://berocket.com/wp-plugins/product-filters
5
  Description: Advanced AJAX Product Filters for WooCommerce
6
+ Version: 1.0.4.6
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
19
 
20
  class BeRocket_AAPF {
21
 
22
+ public static $defaults = array(
23
+ "no_products_message" => "There are no products meeting your criteria",
24
+ "no_products_class" => "",
25
+ "control_sorting" => "0",
26
+ "products_holder_id" => "ul.products",
27
+ "filters_turn_off" => "0",
28
+ "seo_friendly_urls" => "0"
29
+ );
30
 
31
+ function __construct(){
32
+ register_activation_hook(__FILE__, array( __CLASS__, 'br_add_defaults' ) );
33
+ register_uninstall_hook(__FILE__, array( __CLASS__, 'br_delete_plugin_options' ) );
34
 
35
+ add_action( 'admin_menu', array( __CLASS__, 'br_add_options_page' ) );
36
+ add_action( 'admin_init', array( __CLASS__, 'register_br_options' ) );
37
 
38
  add_shortcode( 'br_filters', array( __CLASS__, 'shortcode' ) );
39
 
40
  if( @ $_GET['filters'] and ! @ defined( 'DOING_AJAX' ) ) {
41
+ add_filter( 'pre_get_posts', array( __CLASS__, 'apply_user_filters' ) );
42
+ }
43
+ }
44
 
45
+ public static function br_add_options_page(){
46
+ add_submenu_page( 'woocommerce', 'Product Filters Settings', 'Product Filters', 'manage_options', 'br-product-filters', array( __CLASS__, 'br_render_form' ) );
47
+ }
48
 
49
+ public static function shortcode( $atts = array() ){
50
  $a = shortcode_atts(
51
  array(
52
  'attribute' => '',
60
  ), $atts );
61
  if ( ! $a['attribute'] || ! $a['type'] ) return false;
62
 
63
+ $BeRocket_AAPF_Widget = new BeRocket_AAPF_Widget();
64
+ $BeRocket_AAPF_Widget->widget( array(), $a );
65
+ }
66
 
67
+ public static function br_render_form(){
68
+ include AAPF_TEMPLATE_PATH . "admin-settings.php";
69
+ }
70
 
71
+ public static function apply_user_filters( $query ){
72
  if( $query->is_main_query() and
73
+ ( $query->get( 'post_type' ) == 'product' or $query->get( 'product_cat' ) )
74
+ or
75
+ $query->is_page() && 'page' == get_option( 'show_on_front' ) && $query->get('page_id') == wc_get_page_id('shop')
76
+ ){
77
  br_aapf_args_converter();
78
+ $args = br_aapf_args_parser();
79
 
80
  if( @ $_POST['price'] ){
81
+ list( $_GET['min_price'], $_GET['max_price'] ) = $_POST['price'];
82
+ add_filter( 'loop_shop_post_in', array( 'WC_QUERY', 'price_filter' ) );
83
+ }
84
 
85
+ if ( @ $_POST['limits'] ) {
86
+ add_filter( 'loop_shop_post_in', array( __CLASS__, 'limits_filter' ) );
87
+ }
88
 
89
+ $args_fields = array( 'meta_key', 'tax_query', 'fields', 'where', 'join', 'meta_query' );
90
+ foreach( $args_fields as $args_field ){
91
+ if( @ $args[$args_field] ){
92
+ $query->set( $args_field, $args[$args_field] );
93
+ }
94
+ }
95
+ }
96
 
97
+ return $query;
98
+ }
99
 
100
+ public static function limits_filter( $filtered_posts ){
101
+ global $wpdb;
102
 
103
+ if ( @ $_POST['limits'] ) {
104
+ $matched_products = array( 0 );
105
 
106
+ foreach ( $_POST['limits'] as $v ) {
107
+ $matched_products_query = $wpdb->get_results( $wpdb->prepare("
108
  SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
109
  INNER JOIN $wpdb->term_relationships as tr ON ID = tr.object_id
110
  INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
113
  AND tt.taxonomy = %s AND t.slug BETWEEN %d AND %d
114
  ", $v[0], $v[1], $v[2] ), OBJECT_K );
115
 
116
+ if ( $matched_products_query ) {
117
+ foreach ( $matched_products_query as $product ) {
118
+ if ( $product->post_type == 'product' )
119
+ $matched_products[] = $product->ID;
120
+ if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
121
+ $matched_products[] = $product->post_parent;
122
+ }
123
+ }
124
+ }
125
+
126
+ $matched_products = array_unique( $matched_products );
127
+
128
+ // Filter the id's
129
+ if ( sizeof( $filtered_posts ) == 0) {
130
+ $filtered_posts = $matched_products;
131
+ } else {
132
+ $filtered_posts = array_intersect( $filtered_posts, $matched_products );
133
+ }
134
+ }
135
+
136
+ return (array) $filtered_posts;
137
+ }
138
+
139
+ public static function price_filter( $filtered_posts ){
140
+ global $wpdb;
141
+
142
+ if ( @ $_POST['price'] ) {
143
+ $matched_products = array( 0 );
144
+ $min = floatval( $_POST['price'][0] );
145
+ $max = floatval( $_POST['price'][1] );
146
+
147
+ $matched_products_query = apply_filters( 'woocommerce_price_filter_results', $wpdb->get_results( $wpdb->prepare("
148
  SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
149
  INNER JOIN $wpdb->postmeta ON ID = post_id
150
  WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish' AND meta_key = %s AND meta_value BETWEEN %d AND %d
151
  ", '_price', $min, $max ), OBJECT_K ), $min, $max );
152
 
153
+ if ( $matched_products_query ) {
154
+ foreach ( $matched_products_query as $product ) {
155
+ if ( $product->post_type == 'product' )
156
+ $matched_products[] = $product->ID;
157
+ if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
158
+ $matched_products[] = $product->post_parent;
159
+ }
160
+ }
161
+
162
+ // Filter the id's
163
+ if ( sizeof( $filtered_posts ) == 0) {
164
+ $filtered_posts = $matched_products;
165
+ } else {
166
+ $filtered_posts = array_intersect( $filtered_posts, $matched_products );
167
+ }
168
+
169
+ }
170
+
171
+ return (array) $filtered_posts;
172
+ }
173
+
174
+ /**
175
+ * Get template part (for templates like the slider).
176
+ *
177
+ * @access public
178
+ * @param string $name (default: '')
179
+ * @return void
180
+ */
181
+ public static function br_get_template_part( $name = '' ) {
182
+ $template = '';
183
+
184
+ // Look in your_child_theme/woocommerce-filters/name.php
185
+ if ( $name ) {
186
+ $template = locate_template( "woocommerce-filters/{$name}.php" );
187
+ }
188
+
189
+ // Get default slug-name.php
190
+ if ( ! $template && $name && file_exists( AAPF_TEMPLATE_PATH . "{$name}.php" ) ) {
191
+ $template = AAPF_TEMPLATE_PATH . "{$name}.php";
192
+ }
193
+
194
+ // Allow 3rd party plugin filter template file from their plugin
195
+ $template = apply_filters( 'br_get_template_part', $template, $name );
196
+
197
+
198
+ if ( $template ) {
199
+ load_template( $template, false );
200
+ }
201
+ }
202
+
203
+ public static function register_br_options() {
204
+ register_setting( 'br_filters_plugin_options', 'br_filters_options' );
205
+ }
206
+
207
+ public static function br_add_defaults(){
208
+ $tmp = get_option('br_filters_options');
209
+ if( @$tmp['chk_default_options_db'] == '1' or ! @is_array( $tmp ) ){
210
+ delete_option( 'br_filters_options' );
211
+ update_option( 'br_filters_options', BeRocket_AAPF::$defaults );
212
+ }
213
+ }
214
+
215
+ public static function br_delete_plugin_options(){
216
+ delete_option( 'br_filters_options' );
217
+ }
218
 
219
  }
220