PluginProbe
Filter Everything — WordPress & WooCommerce Filters / trunk
Filter Everything — WordPress & WooCommerce Filters vtrunk
1.9.6 1.9.5 1.9.4 1.9.3 1.9.2.2 1.9.2.1 trunk 1.2.1 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.1 1.4.4 1.4.5 1.4.8 1.4.9 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 All 51 releases
filter-everything / src / wpc-third-party.php

wpc-third-party.php in Filter Everything — WordPress & WooCommerce Filters trunk, at src/wpc-third-party.php

1,354 lines 66.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined('ABSPATH') ) {
4 exit;
5 }
6
7 function flrt_is_woocommerce()
8 {
9 if( class_exists('WooCommerce') ){
10 return true;
11 }
12 return false;
13 }
14
15 function flrt_is_acf()
16 {
17 if( class_exists( 'ACF' ) ){
18 return true;
19 }
20 return false;
21 }
22
23 function flrt_get_mobile_width(){
24 return apply_filters( 'wpc_mobile_width', 768 );
25 }
26
27 /**
28 * @feature for other popular themes there is possibility to add action to hook get_template_part_{$slug}
29 * But it seems we need to detect what current theme is enabled
30 */
31 if( ! function_exists('flrt_wp') ){
32
33 function flrt_wp(){
34 $theme_dependencies = flrt_get_theme_dependencies();
35
36 if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){
37
38 if( flrt_get_experimental_option('disable_buttons') !== 'on' ) {
39
40 if (flrt_is_woocommerce()) { // It means WooCommerce installed
41
42 if( is_woocommerce() ){ // It means is a WooCommerce page
43 add_action('woocommerce_before_shop_loop', 'flrt_filters_button', 5);
44 add_action('woocommerce_no_products_found', 'flrt_filters_button', 5);
45 }else{
46 if (isset($theme_dependencies['button_hook']) && is_array($theme_dependencies['button_hook'])) {
47 foreach ($theme_dependencies['button_hook'] as $button_hook) {
48 add_action($button_hook, function() use ($button_hook) {
49 flrt_filters_button(0, '', $button_hook);
50 }, 15);
51 }
52 }
53 }
54
55 } else {
56 if (isset($theme_dependencies['button_hook']) && is_array($theme_dependencies['button_hook'])) {
57 foreach ($theme_dependencies['button_hook'] as $button_hook) {
58 add_action($button_hook, function() use ($button_hook) {
59 flrt_filters_button(0, '', $button_hook);
60 }, 15);
61 }
62 }
63 }
64 }
65
66 }
67
68 // Add selected terms to the top
69 $chips_hooks = flrt_get_option('show_terms_in_content', []);
70
71 if( $chips_hooks ){
72 if( is_array( $chips_hooks ) && ! empty( $chips_hooks ) ){
73 foreach ( $chips_hooks as $hook ){
74 add_action( $hook, 'flrt_add_selected_terms_above_the_top' );
75 }
76 }
77 }
78 }
79 }
80
81 function wpc_add_selected_terms_above_the_top(){
82 _deprecated_function( __FUNCTION__, '1.0.7', 'flrt_add_selected_terms_above_the_top()' );
83 flrt_add_selected_terms_above_the_top();
84 }
85
86 function flrt_add_selected_terms_above_the_top()
87 {
88 flrt_show_selected_terms(true);
89 }
90
91 function flrt_get_theme_dependencies(){
92 $current_theme = strtolower( get_template() );
93
94 $theme_dependencies = array(
95 'storefront' => array(
96 'posts_container' => '#primary',
97 'sidebar_container' => '#secondary',
98 'primary_color' => '#96588a',
99 'button_hook' => array('storefront_content_top'),
100 'chips_hook' => array('storefront_loop_before')
101 ),
102 'hello-elementor' => array(
103 'posts_container' => '.page-content',
104 'sidebar_container' => '',
105 'primary_color' => '#CC3366',
106 'button_hook' => '',
107 'chips_hook' => ''
108 ),
109 'astra' => array(
110 'posts_container' => '#primary',
111 'sidebar_container' => '#secondary',
112 'primary_color' => '#0274be',
113 'button_hook' => '',
114 'chips_hook' => ''
115 ),
116 'twentyeleven' => array(
117 'posts_container' => '#primary',
118 'sidebar_container' => '#secondary',
119 'primary_color' => '#1982d1',
120 'button_hook' => '',
121 'chips_hook' => ''
122 ),
123 'twentytwelve' => array(
124 'posts_container' => '#primary',
125 'sidebar_container' => '#secondary',
126 'primary_color' => '#21759b',
127 'button_hook' => '',
128 'chips_hook' => ''
129 ),
130 'twentyfourteen' => array(
131 'posts_container' => '#primary',
132 'sidebar_container' => '#secondary',
133 'primary_color' => '#24890d',
134 'button_hook' => '',
135 'chips_hook' => ''
136 ),
137 'twentyfifteen' => array(
138 'posts_container' => '#primary',
139 'sidebar_container' => '#secondary', // There are problems on mobile
140 // because of sidebar is hidden on mobile until user open header menu.
141 'primary_color' => '#333333',
142 'button_hook' => '',
143 'chips_hook' => ''
144 ),
145 'twentysixteen' => array(
146 'posts_container' => '#primary',
147 'sidebar_container' => '#secondary',
148 'primary_color' => '#007acc',
149 'button_hook' => '',
150 'chips_hook' => ''
151 ),
152 'twentyseventeen' => array(
153 'posts_container' => '#primary',
154 'sidebar_container' => '#secondary',
155 'primary_color' => '#222222',
156 'button_hook' => '',
157 'chips_hook' => ''
158 ),
159 'twentynineteen' => array(
160 'posts_container' => '#primary',
161 'sidebar_container' => '#secondary',
162 'primary_color' => '#0073aa',
163 'button_hook' => '',
164 'chips_hook' => ''
165 ),
166 'twentytwentyfive' => array(
167 'posts_container' => '#wp--skip-link--target',
168 'sidebar_container' => '',
169 'primary_color' => '#0073aa',
170 'button_hook' => '',
171 'chips_hook' => ''
172 ),
173 'twentytwenty' => array(
174 'posts_container' => '#site-content',
175 'sidebar_container' => '',
176 'primary_color' => '#cd2653',
177 'button_hook' => '',
178 'chips_hook' => ''
179 ),
180 'twentytwentyone' => array(
181 'posts_container' => '#content',
182 'sidebar_container' => '.widget-area',
183 'primary_color' => '#28303d',
184 'button_hook' => '',
185 'chips_hook' => ''
186 ),
187 'popularfx' => array(
188 'posts_container' => '#primary',
189 'sidebar_container' => '#secondary',
190 'primary_color' => '#0072b7',
191 'button_hook' => '',
192 'chips_hook' => ''
193 ),
194 'oceanwp' => array(
195 'posts_container' => '#primary',
196 'sidebar_container' => '#right-sidebar',
197 'primary_color' => '#13aff0',
198 'button_hook' => array('ocean_before_content'),
199 'chips_hook' => array('ocean_before_content')
200 ),
201 'kadence' => array(
202 'posts_container' => '#main',
203 'sidebar_container' => '#secondary',
204 'primary_color' => '#3182ce',
205 'button_hook' => array('kadence_before_main_content'),
206 'chips_hook' => array('kadence_before_main_content')
207 ),
208 'zakra' => array(
209 'posts_container' => '#primary',
210 'sidebar_container' => '#secondary',
211 'primary_color' => '#269bd1',
212 'button_hook' => array('zakra_before_posts_the_loop'),
213 'chips_hook' => array('zakra_before_posts_the_loop')
214 ),
215 'neve' => array(
216 'posts_container' => '.nv-index-posts',
217 'sidebar_container' => '#secondary', // '.nv-sidebar-wrap',
218 'primary_color' => '#393939',
219 'button_hook' => array('neve_before_loop'),
220 'chips_hook' => array('neve_before_loop')
221 ),
222 'hestia' => array(
223 'posts_container' => '#woo-products-wrap',
224 'sidebar_container' => '#secondary',
225 'primary_color' => '#e91e63',
226 'button_hook' => array('hestia_before_index_posts_loop'),
227 'chips_hook' => array('hestia_before_index_posts_loop')
228 ),
229 'colibri-wp' => array(
230 'posts_container' => '.main-row-inner .h-col:not(.colibri-sidebar)',
231 'sidebar_container' => '.colibri-sidebar',
232 'primary_color' => '#03a9f4',
233 'button_hook' => '',
234 'chips_hook' => ''
235 ),
236 'teluro' => array(
237 'posts_container' => '.main-row-inner .h-col:not(.colibri-sidebar)',
238 'sidebar_container' => '.colibri-sidebar',
239 'primary_color' => '#f26559',
240 'button_hook' => '',
241 'chips_hook' => ''
242 ),
243 'numinous' => array(
244 'posts_container' => '#primary',
245 'sidebar_container' => '#secondary',
246 'primary_color' => '#f4ab00',
247 'button_hook' => array('numinous_content'),
248 'chips_hook' => ''
249 ),
250 'sydney' => array(
251 'posts_container' => '#primary',
252 'sidebar_container' => '#secondary',
253 'primary_color' => '#d65050',
254 'button_hook' => array('sydney_before_content'),
255 'chips_hook' => ''
256 ),
257 // Commercial themes
258 'avada' => array(
259 'posts_container' => '#content',
260 'sidebar_container' => '#sidebar',
261 'primary_color' => '#65bc7b',
262 'button_hook' => array('avada_before_main_container'),
263 'chips_hook' => ''
264 ),
265 'generatepress' => array(
266 'posts_container' => '#primary',
267 'sidebar_container' => '.sidebar',
268 'primary_color' => '#1e73be',
269 'button_hook' => array('generate_before_main_content'),
270 'chips_hook' => array('generate_before_main_content')
271 ),
272 'the7' => array(
273 'posts_container' => '#content',
274 'sidebar_container' => '#sidebar',
275 'primary_color' => '',
276 'button_hook' => '',
277 'chips_hook' => ''
278 ),
279 'dt-the7' => array(
280 'posts_container' => '#content',
281 'sidebar_container' => '#sidebar',
282 'primary_color' => '',
283 'button_hook' => '',
284 'chips_hook' => ''
285 ),
286 'flatsome' => array(
287 'posts_container' => '.shop-container',
288 'sidebar_container' => '#shop-sidebar',
289 'primary_color' => '#446084',
290 'button_hook' => '',
291 'chips_hook' => ''
292 ),
293 'betheme' => array(
294 'posts_container' => '.sections_group',
295 'sidebar_container' => '.sidebar',
296 'primary_color' => '',
297 'button_hook' => '',
298 'chips_hook' => ''
299 ),
300 'bridge' => array(
301 'posts_container' => '.container .column1',
302 'sidebar_container' => '',
303 'primary_color' => '',
304 'button_hook' => '',
305 'chips_hook' => ''
306 ),
307 'impreza' => array(
308 'posts_container' => '#page-content .w-grid-list',
309 'sidebar_container' => '',
310 'primary_color' => '',
311 'button_hook' => '',
312 'chips_hook' => ''
313 ),
314 'enfold' => array(
315 'posts_container' => 'main.content',
316 'sidebar_container' => '',
317 'primary_color' => '',
318 'button_hook' => '',
319 'chips_hook' => ''
320 ),
321 'porto' => array(
322 'posts_container' => '#content',
323 'sidebar_container' => '',
324 'primary_color' => '',
325 'button_hook' => '',
326 'chips_hook' => ''
327 ),
328 'genesis' => array(
329 'posts_container' => '#primary',
330 'sidebar_container' => '#secondary',
331 'primary_color' => '',
332 'button_hook' => '',
333 'chips_hook' => ''
334 ),
335 'woodmart' => array(
336 'posts_container' => '.site-content',
337 'sidebar_container' => '#secondary',
338 'primary_color' => '#83b735',
339 'button_hook' => '',
340 'chips_hook' => array( 'woodmart_shop_filters_area', 'woodmart_main_loop')
341 ),
342
343 'bricks' => array(
344 'posts_container' => '.brxe-container',
345 'sidebar_container' => '',
346 'primary_color' => '',
347 'button_hook' => array('bricks_after_header'),
348 'chips_hook' => ''
349 ),
350 'bb-theme' => array(
351 'posts_container' => '#fl-main-content',
352 'sidebar_container' => '',
353 'primary_color' => '',
354 'button_hook' => array('fl_content_open'),
355 'chips_hook' => ''
356 ),
357 );
358
359 $theme_dependencies = apply_filters( 'wpc_theme_dependencies', $theme_dependencies );
360
361 if( isset( $theme_dependencies[ $current_theme ] ) ){
362 return $theme_dependencies[ $current_theme ];
363 }
364
365 return array(
366 'posts_container' => false,
367 'sidebar_container' => false,
368 'primary_color' => false,
369 'button_hook' => array(),
370 'chips_hook' => array()
371 );
372 }
373
374 add_action( 'wp', 'flrt_wp' );
375
376 if( ! function_exists('flrt_set_posts_container') ){
377 function flrt_set_posts_container( $theme_posts_container )
378 {
379 $theme_dependencies = flrt_get_theme_dependencies();
380
381 if( isset( $theme_dependencies[ 'posts_container' ] ) ){
382 return $theme_dependencies[ 'posts_container' ];
383 }
384
385 return $theme_posts_container;
386 }
387 }
388
389 function flrt_set_theme_color($color ){
390
391 $theme_dependencies = flrt_get_theme_dependencies();
392
393 if( $theme_dependencies['primary_color'] ){
394 $color = $theme_dependencies['primary_color'];
395 }
396
397 return $color;
398 }
399
400 if( ! function_exists('flrt_init') ){
401 function flrt_init()
402 {
403 // Set correct theme posts container
404 add_filter('wpc_theme_posts_container', 'flrt_set_posts_container');
405
406 // Set correct theme color
407 add_filter('wpc_theme_color', 'flrt_set_theme_color');
408
409 //
410 if( flrt_is_acf() ) {
411 add_filter( 'wpc_pre_save_filter', 'flrt_maybe_acf_field' );
412 add_filter( 'wpc_default_sorting_terms', 'flrt_acf_terms_order', 10, 2 );
413 }
414 }
415 }
416 add_action('init', 'flrt_init');
417
418 function flrt_wpml_active(){
419 if( defined('WPML_PLUGIN_BASENAME') ){
420 return true;
421 }
422 return false;
423 }
424
425 add_action( 'elementor/editor/before_enqueue_scripts', 'flrt_include_elementor_script' );
426 function flrt_include_elementor_script(){
427 $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
428 $ver = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? rand(0, 1000) : FLRT_PLUGIN_VER;
429 wp_enqueue_script('wpc-widgets', FLRT_PLUGIN_DIR_URL . 'assets/js/wpc-widgets' . $suffix . '.js', ['jquery', 'jquery-ui-sortable'], $ver, true );
430 wp_enqueue_style('wpc-widgets', FLRT_PLUGIN_DIR_URL . 'assets/css/wpc-widgets' . $suffix . '.css', [], $ver );
431
432 $l10n = array(
433 'wpcItemNum' => esc_html__( 'Item #', 'filter-everything')
434 );
435 wp_localize_script( 'wpc-widgets', 'wpcWidgets', $l10n );
436 }
437
438 /*
439 * Polylang compatibility functions
440 * */
441 function flrt_maybe_has_translation( $post_id, $lang = '' ){
442
443 if( function_exists( 'pll_get_post' ) ){
444 $translation_post_id = pll_get_post( $post_id, $lang );
445 if( $translation_post_id ){
446 $post_id = $translation_post_id;
447 }
448 }
449
450 return $post_id;
451 }
452
453 function flrt_pll_pro_active(){
454 if ( defined('POLYLANG_PRO') ) {
455 return true;
456 }
457 return false;
458 }
459 // Allow Filter Sets to be translatable if Polylang PRO activated
460 // This make sense for Filter Sets with common locations only
461 add_action( 'after_setup_theme', 'flrt_pll_init', 20 );
462 function flrt_pll_init(){
463 if( flrt_pll_pro_active() && defined('FLRT_ALLOW_PLL_TRANSLATIONS') && FLRT_ALLOW_PLL_TRANSLATIONS ){
464 add_filter( 'pll_get_post_types', 'flrt_add_cpt_to_pll', 10, 2 );
465 }
466 }
467
468 function flrt_add_cpt_to_pll( $post_types, $is_settings ) {
469 if ( $is_settings ) {
470 unset( $post_types[ FLRT_FILTERS_SET_POST_TYPE ], $post_types[ FLRT_FILTERS_SET_POST_TYPE ] );
471 } else {
472 $post_types[ FLRT_FILTERS_SET_POST_TYPE ] = FLRT_FILTERS_SET_POST_TYPE;
473 if( defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO ) {
474 $post_types[ FLRT_SEO_RULES_POST_TYPE ] = FLRT_SEO_RULES_POST_TYPE;
475 }
476 }
477 return $post_types;
478 }
479
480 /**
481 * Adds compatibility the Price filter with multi-currency plugins WOOCS and CURCY
482 * @since 1.7.12
483 */
484 add_action('init', 'flrt_add_currencies_support');
485 function flrt_add_currencies_support() {
486 if ( flrt_is_woocommerce() ) {
487 // For the FOX - Currency Switcher Professional for WooCommerce
488 if ( defined( 'WOOCS_PLUGIN_NAME' ) && WOOCS_PLUGIN_NAME ) {
489 // Converts values into selected currency. Visible in the range slider form
490 add_filter( 'wpc_set_num_shift', 'flrt_set_woocs_shift', 10, 2 );
491 function flrt_set_woocs_shift( $value, $entity_name ) {
492 global $WOOCS;
493
494 if ( $entity_name === '_price' ) {
495 if ( property_exists( $WOOCS, 'default_currency' ) && property_exists( $WOOCS, 'current_currency' ) ) {
496 if ( ! $WOOCS->default_currency || ! $WOOCS->current_currency ) {
497 return $value;
498 }
499
500 if ( $WOOCS->default_currency !== $WOOCS->current_currency && method_exists( $WOOCS, 'convert_from_to_currency' ) ) {
501 $value = $WOOCS->convert_from_to_currency( $value, $WOOCS->default_currency, $WOOCS->current_currency );
502 }
503 }
504 }
505
506 return $value;
507 }
508
509 // Converts values back to default currency for WP_Query
510 add_filter( 'wpc_unset_num_shift', 'flrt_unset_woocs_shift', 10, 2 );
511 function flrt_unset_woocs_shift( $value, $entity_name ) {
512 global $WOOCS;
513
514 if ( $entity_name === '_price' ) {
515 if ( property_exists( $WOOCS, 'default_currency' ) && property_exists( $WOOCS, 'current_currency' ) ) {
516 if ( ! $WOOCS->default_currency || ! $WOOCS->current_currency ) {
517 return $value;
518 }
519
520 $precision = 2;
521 if( method_exists( $WOOCS, 'get_currency_price_num_decimals' ) ) {
522 $precision = $WOOCS->get_currency_price_num_decimals( $WOOCS->current_currency, $WOOCS->price_num_decimals );
523 }
524
525 if ( $WOOCS->default_currency !== $WOOCS->current_currency && method_exists( $WOOCS, 'convert_from_to_currency' ) ) {
526 $value = $WOOCS->convert_from_to_currency( $value, $WOOCS->current_currency, $WOOCS->default_currency );
527 $value = round( $value, $precision );
528 }
529 }
530 }
531
532 return $value;
533 }
534 }
535
536 // For the CURCY - Multi Currency for WooCommerce
537 if ( defined( 'WOOMULTI_CURRENCY_F_VERSION' ) && WOOMULTI_CURRENCY_F_VERSION ) {
538 // Converts values into selected currency. Visible in the range slider form
539 add_filter( 'wpc_set_num_shift', 'flrt_set_curcy_shift', 10, 2 );
540 function flrt_set_curcy_shift( $value, $entity_name ) {
541
542 if ( $entity_name === '_price' ) {
543 if ( method_exists( 'WOOMULTI_CURRENCY_F_Data', 'get_ins' ) && function_exists('wmc_get_price' ) ) {
544 $settings = WOOMULTI_CURRENCY_F_Data::get_ins();
545
546 if ( ! method_exists( $settings, 'get_current_currency' ) || ! method_exists( $settings, 'get_default_currency' ) ) {
547 return $value;
548 }
549
550 $currency = $settings->get_current_currency();
551 $default_currency = $settings->get_default_currency();
552
553 if ( $currency !== $default_currency ) {
554 $value = wmc_get_price( $value, $currency );
555 }
556 }
557 }
558
559 return $value;
560 }
561
562 // Converts values back to default currency for WP_Query
563 add_filter( 'wpc_unset_num_shift', 'flrt_unset_curcy_shift', 10, 2 );
564 function flrt_unset_curcy_shift( $value, $entity_name ) {
565
566 if ( $entity_name === '_price' ) {
567 if ( method_exists( 'WOOMULTI_CURRENCY_F_Data', 'get_ins' ) && function_exists('wmc_revert_price' ) ) {
568 $settings = WOOMULTI_CURRENCY_F_Data::get_ins();
569
570 if ( ! method_exists( $settings, 'get_current_currency' ) || ! method_exists( $settings, 'get_default_currency' ) ) {
571 return $value;
572 }
573
574 $currency = $settings->get_current_currency();
575 $default_currency = $settings->get_default_currency();
576
577 if ( $currency !== $default_currency ) {
578 $value = wmc_revert_price( $value );
579 }
580 }
581 }
582
583 return $value;
584 }
585 }
586 }
587 }
588
589 /**
590 * Removes WooCommerce Product Query post clauses for the price filter
591 * @since 1.7.12
592 */
593 function flrt_remove_product_query_post_clauses( $wp_query, $WC_query ) {
594 $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
595
596 if ( $wpManager->getQueryVar( 'wpc_is_filter_request' ) ) {
597 remove_filter('posts_clauses', array( $WC_query, 'product_query_post_clauses' ), 10, 2);
598 }
599
600 return $wp_query;
601 }
602
603 add_filter('wpc_check_broken_filter', function ($is_broken, $query) {
604 $detector_class = 'FilterEverything\\Filter\\WP_Query_Source_Detector';
605 $is_allowed_method = 'is_allowed';
606 $source_var = 'flrt_detected_source';
607
608 if (defined('FLRT_FILTERS_PRO')) {
609 if (defined('FLRT_PRO_BUILDER_KEY')) {
610 $builder_key = apply_filters('wpc_builder_key_pro', $query->get($source_var), constant('FLRT_PRO_BUILDER_KEY'));
611
612 if ($detector_class::$is_allowed_method($builder_key)) {
613 return false;
614 }
615 }
616 }
617
618 if (!defined('FLRT_FILTERS_PRO')) {
619 $builder_key = apply_filters('wpc_builder_key', $query->get($source_var), $detector_class::$builder_key);
620
621 if ($detector_class::$is_allowed_method($builder_key)) {
622 return false;
623 }
624 }
625
626 return true;
627 }, 10, 2);
628
629 function flrt_is_dokan() {
630 return function_exists('dokan');
631 }
632
633 function flrt_maybe_acf_field( $filter ){
634 if( $filter['entity'] === 'post_meta' ) {
635 global $wpdb;
636 // Try to check if this is ACF field
637 $sql[] = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts}";
638 $sql[] = "WHERE {$wpdb->posts}.post_excerpt = %s";
639 $sql[] = "AND {$wpdb->posts}.post_type = %s";
640 $sql[] = "ORDER BY {$wpdb->posts}.ID ASC";
641
642 $sql = implode(' ', $sql );
643 $sql = $wpdb->prepare( $sql, $filter['e_name'], 'acf-field' );
644 $results = $wpdb->get_results( $sql, ARRAY_A );
645
646 if ( ! empty( $results ) ) {
647 $ids = [];
648 foreach ( $results as $single_result ) {
649 if( isset( $single_result['ID'] ) ){
650 $ids[] = $single_result['ID'];
651 }
652 }
653 $acf_field_ids = implode( ',', $ids );
654
655 if( ! empty( $acf_field_ids ) ){
656 $filter['acf_fields'] = $acf_field_ids;
657 }
658 }
659 }
660
661 return $filter;
662 }
663
664 function flrt_acf_terms_order( $entity_items, $filter ){
665
666 if( isset( $filter['acf_fields'] ) && $filter['acf_fields'] !== '' ) {
667 global $wpdb;
668 // Here we have to get ACF fields by their IDs and sort terms in according to
669 // the order in the field.
670 $sql = [];
671 $acf_field_ids = preg_replace( '/^[\d]\,/', '', $filter['acf_fields'] );
672 $sql[] = "SELECT {$wpdb->posts}.post_content FROM {$wpdb->posts}";
673 $sql[] = "WHERE {$wpdb->posts}.ID IN( {$acf_field_ids} )";
674 $sql[] = "ORDER BY {$wpdb->posts}.ID ASC";
675 $sql = implode(' ', $sql );
676
677 $results = $wpdb->get_results( $sql, ARRAY_A );
678
679 if( empty( $results ) ) {
680 return $entity_items;
681 }
682
683 $field_terms = [];
684 foreach ( $results as $acf_field ){
685 if( isset( $acf_field['post_content'] ) ) {
686 $field_options = maybe_unserialize( $acf_field['post_content'] );
687
688 if( isset( $field_options['choices'] ) && is_array( $field_options['choices'] ) ){
689 foreach ( $field_options['choices'] as $value => $label ){
690 if( ! isset( $field_terms[$value] ) ) {
691 $field_terms[$value] = $label;
692 }
693 }
694 }
695 }
696 }
697
698 $current_items = $entity_items;
699 $sorted_items = [];
700
701 foreach ( $field_terms as $tslug => $tvalue ) {
702 $tslug = sanitize_title( $tslug );
703
704 if( isset( $current_items[ $tslug ] ) ) {
705 $term_object = $current_items[ $tslug ];
706 $term_object->name = $tvalue;
707 $sorted_items[ $tslug ] = $term_object;
708 unset( $current_items[ $tslug ] );
709 }
710 }
711
712 if( ! empty( $current_items ) ){
713 foreach ( $current_items as $slug => $item ){
714 $sorted_items[$slug] = $item;
715 }
716 }
717 $entity_items = $sorted_items;
718 }
719
720 return $entity_items;
721 }
722
723 /**
724 * Adds correct pagination URLs to the Load more/Infinite scroll button for Elementor posts block
725 */
726 add_filter( 'elementor/widget/render_content', 'flrt_elementor_load_more_anchor', 10, 2 );
727 function flrt_elementor_load_more_anchor( $widget_content, $module ){
728 // Nothing is needed if there is no Filter request
729 if( ! flrt_is_filter_request() ){
730 return $widget_content;
731 }
732
733 if( $module instanceof ElementorPro\Modules\Posts\Widgets\Posts ){
734 global $wp_rewrite;
735
736 $urlManager = \FilterEverything\Filter\Container::instance()->getUrlManager();
737 $current_page = $module->get_current_page();
738 $next_page = intval( $current_page ) + 1;
739 $data_next_page = $module->get_wp_link_page( $next_page );
740 $rewrite = $wp_rewrite->wp_rewrite_rules();
741
742 /*
743 * Loop widgets (Loop Grid/Loop Carousel) paginate with a widget-scoped
744 * query arg (?e-page-<widget id>=N) instead of /page/N/, so the
745 * path-based base replacement below never matches. Swap the base for
746 * the filtered URL directly and carry the pagination args over.
747 */
748 $next_page_args = array();
749 $next_url_parts = parse_url( $data_next_page );
750 if ( isset( $next_url_parts['query'] ) ) {
751 parse_str( $next_url_parts['query'], $next_page_args );
752 }
753
754 $e_page_args = array();
755 foreach ( $next_page_args as $arg_key => $arg_value ) {
756 if ( strpos( $arg_key, 'e-page-' ) === 0 ) {
757 $e_page_args[ $arg_key ] = $arg_value;
758 }
759 }
760
761 if ( ! empty( $e_page_args ) ) {
762 // The current request may already contain pagination args (page 2+)
763 $data_next_page = remove_query_arg( array_keys( $e_page_args ), $urlManager->getFormActionOrFullPageUrl( true ) );
764 foreach ( $e_page_args as $arg_key => $arg_value ) {
765 $data_next_page = flrt_add_query_arg( $arg_key, $arg_value, $data_next_page );
766 }
767 } else if ( defined('FLRT_PERMALINKS_ENABLED') && FLRT_PERMALINKS_ENABLED ) {
768 // This is ok when permalinks are enabled.
769 $data_next_page = str_replace( $urlManager->removePaginationBase( $data_next_page ), $urlManager->getFormActionOrFullPageUrl(), $data_next_page );
770 $uri_components = explode( "?", $urlManager->getFormActionOrFullPageUrl( true ) );
771 if( isset( $uri_components[1] ) ){
772 $data_next_page = $data_next_page . '?'.$uri_components[1];
773 }
774 } else if ( ! FLRT_PERMALINKS_ENABLED && ! empty( $rewrite ) ) {
775 // WordPress permalinks are Enabled, but Filter Everything permalinks are Disabled
776 $uri_components = explode( "?", $urlManager->getFormActionOrFullPageUrl( true ) );
777 // If URI part after ? exists
778 if( isset( $uri_components[1] ) ){
779 $data_next_page = $data_next_page . '?'.$uri_components[1];
780 }
781 } else {
782 // No permalinks at all
783 $current_page_url = $urlManager->getFormActionOrFullPageUrl( true );
784 $url_parts = parse_url( $data_next_page );
785 if( isset( $url_parts['query'] ) ){
786 parse_str( $url_parts['query'], $params );
787 if( isset( $params['page'] ) && $params['page'] ) {
788 $data_next_page = flrt_add_query_arg( 'page', $params['page'], $current_page_url );
789 }
790 }
791 }
792
793 $widget_content = preg_replace('%data-next-page\="[^"]+"%', 'data-next-page="' . $data_next_page . '"', $widget_content);
794 }
795
796 return $widget_content;
797 }
798
799 add_filter( 'wpc_remove_pagination_base', 'flrt_remove_pagination_base' );
800 function flrt_remove_pagination_base( $url ){
801 global $wp_rewrite;
802
803 $rewrite = $wp_rewrite->wp_rewrite_rules();
804 $url = ( ! empty( $rewrite ) ) ? user_trailingslashit( $url ) : rtrim( $url, '/' ) . '/';
805
806 return $url;
807 }
808
809 function flrt_is_woo_discount_rules()
810 {
811 $check_woo_discount_rules = apply_filters('flrt_woo_discount_rules_enabled', true);
812 if(!$check_woo_discount_rules) return false;
813 if( flrt_is_woocommerce() &&
814 class_exists('Wdr\App\Helpers\Woocommerce') &&
815 class_exists('Wdr\App\Controllers\Base') &&
816 class_exists('Wdr\App\Helpers\Rule') &&
817 class_exists('Wdr\App\Controllers\ManageDiscount') &&
818 class_exists('Wdr\App\Controllers\DiscountCalculator') &&
819 class_exists('Wdr\App\Models\DBTable')
820 )
821 {
822 $tb_table = new Wdr\App\Models\DBTable();
823 $wdr_rules = $tb_table::getRules();
824 if(!empty($wdr_rules)){
825 $discount_types = [];
826 foreach ($wdr_rules as $rule){
827 $discount_types[] = $rule->discount_type;
828 }
829 $allowed_discount_types = ['wdr_simple_discount', 'wdr_bulk_discount', 'wdr_set_discount'];
830 if(!empty(array_intersect($allowed_discount_types, $discount_types))){
831 return true;
832 }
833 }
834 }
835 return false;
836 }
837
838 function flrt_is_elementor_active()
839 {
840 return did_action( 'elementor/loaded' );
841 }
842
843 if ( flrt_is_elementor_active() ) {
844 function wpc_add_elementor_widget_categories( $elements_manager ) {
845 $pro_text = (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO)
846 ? ' ' .esc_html__('PRO', 'filter-everything')
847 : '';
848
849 $elements_manager->add_category(
850 'filter-everything',
851 [
852 'title' => esc_html__( 'Filter Everything', 'filter-everything' ) . $pro_text,
853 'icon' => 'fa-solid fa-filter',
854 ]
855 );
856 }
857 add_action( 'elementor/elements/categories_registered', 'wpc_add_elementor_widget_categories' );
858
859 function wpc_register_elementor_widget( $widgets_manager ) {
860
861 flrt_include('src/Admin/Widgets/ElementorWidgets/ChipsElementorWidget.php');
862 flrt_include('src/Admin/Widgets/ElementorWidgets/FiltersElementorWidget.php');
863 flrt_include('src/Admin/Widgets/ElementorWidgets/SortingElementorWidget.php');
864
865 $widgets_manager->register( new \FilterEverything\Filter\ChipsElementorWidget() );
866 $widgets_manager->register( new \FilterEverything\Filter\FiltersElementorWidget() );
867 $widgets_manager->register( new \FilterEverything\Filter\SortingElementorWidget() );
868
869 }
870 add_action( 'elementor/widgets/register', 'wpc_register_elementor_widget' );
871
872 add_action( 'elementor/editor/after_enqueue_styles', function() {
873 wp_enqueue_style(
874 'filter-everything-elementor',
875 FLRT_PLUGIN_DIR_URL . 'assets/css/elementor-icon.css'
876 );
877 $css = '
878 .wpc-fe-icon {
879 background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUzIDUzIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA1MyA1MyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTMgNTM7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCiAgICAgICAgICAgICAgIDxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQogICAgICAgICAgICAgICAgLnN0MHtkaXNwbGF5Om5vbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDF7ZGlzcGxheTppbmxpbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDN7ZmlsbDojZmZmZmZmO30NCiAgICAgICAgICAgICAgICAuc3Q0e2Rpc3BsYXk6bm9uZTtmaWxsOiNmZmZmZmY7fQ0KICAgICAgICAgICAgICAgIC5zdDV7ZmlsbDpub25lO2ZpbGwtb3BhY2l0eTowO3N0cm9rZTojZmZmZmZmO3N0cm9rZS13aWR0aDozO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCiAgICAgICAgICAgICAgICAuc3Q2e2ZpbGw6bm9uZTtmaWxsLW9wYWNpdHk6MDtzdHJva2U6I2ZmZmZmZjtzdHJva2Utd2lkdGg6MjtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQogICAgICAgICAgICAgICA8L3N0eWxlPg0KICAgICAgICAgICAgICAgPGcgaWQ9IkxheWVyXzJfMDAwMDAwNDc3NzA3MTk3MTAxMTA3NDIyMzAwMDAwMDM5MjM5NTE2MjYxNDg4NDk1NTdfIiBjbGFzcz0ic3QwIj4NCiAgICAgICAgICAgICAgICA8cmVjdCB4PSIwIiB5PSIwIiBjbGFzcz0ic3QxIiB3aWR0aD0iNTMuMSIgaGVpZ2h0PSI1My4xIi8+DQogICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICA8ZyBpZD0iTGF5ZXJfMV8wMDAwMDE2MjMzMzEwMzI2NTgwNjk4MTUzMDAwMDAxNzE0NjYyNDI0NzU5MTY3NDU1Nl8iPg0KICAgICAgICAgICAgICAgIDxnPg0KICAgICAgICAgICAgICAgICAgIDxkZWZzPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGlkPSJTVkdJRF8xXyIgZD0iTTAsMGg1M3Y1M0gwVjB6IE0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNSAgICAgQzIwLjgsMzYuMSwyMS45LDM3LjIsMjMuMywzNy4yeiBNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6ICAgICAgTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgICAgPC9kZWZzPg0KICAgICAgICAgICAgICAgICAgIDxjbGlwUGF0aCBpZD0iU1ZHSURfMDAwMDAxMTI2MDgzNDA4MDQyNDU0NDI0NjAwMDAwMTM5ODYyMTkxNzgxOTkwODYyNDRfIj4NCiAgICAgICAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNTVkdJRF8xXyIgc3R5bGU9Im92ZXJmbG93OnZpc2libGU7Ii8+DQogICAgICAgICAgICAgICAgICAgPC9jbGlwUGF0aD4NCiAgICAgICAgICAgICAgICAgICA8ZyBpZD0iQmFyc0NsaXBwZWQiIHN0eWxlPSJjbGlwLXBhdGg6dXJsKCNTVkdJRF8wMDAwMDExMjYwODM0MDgwNDI0NTQ0MjQ2MDAwMDAxMzk4NjIxOTE3ODE5OTA4NjI0NF8pOyI+DQogICAgICAgICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0MyIgZD0iTTM5LjksMzEuNUwxOCwzNy4zYy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEM0MC44LDMwLjcsNDAuNSwzMS4zLDM5LjksMzEuNXoiLz4NCiAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMzguMSwyNC42bC0yMS45LDUuOWMtMC42LDAuMi0xLjItMC4yLTEuNC0wLjhjLTAuMi0wLjYsMC4yLTEuMiwwLjgtMS40bDIxLjktNS45YzAuNi0wLjIsMS4yLDAuMiwxLjQsMC44ICAgICBDMzksMjMuOCwzOC43LDI0LjUsMzguMSwyNC42eiIvPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zNi4yLDE3LjlsLTIxLjksNS45Yy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEMzNy4yLDE3LjEsMzYuOCwxNy43LDM2LjIsMTcuOXoiLz4NCiAgICAgICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNUMyMC44LDM2LjEsMjEuOSwzNy4yLDIzLjMsMzcuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLjksMzguMmMtMS45LDAuNS0zLjgtMC42LTQuMy0yLjVjLTAuNS0xLjksMC42LTMuOCwyLjUtNC4zczMuOCwwLjYsNC4zLDIuNUMyNi45LDM1LjgsMjUuOCwzNy43LDIzLjksMzguMiAgIHogTTIyLjYsMzMuMmMtMC45LDAuMi0xLjQsMS4xLTEuMSwyYzAuMiwwLjksMS4xLDEuNCwyLDEuMWMwLjktMC4yLDEuNC0xLjEsMS4xLTJDMjQuMywzMy41LDIzLjQsMzMsMjIuNiwzMy4yeiIvPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0zNC4xLDI4LjJjLTEuOSwwLjUtMy44LTAuNi00LjMtMi41czAuNi0zLjgsMi41LTQuM2MxLjktMC41LDMuOCwwLjYsNC4zLDIuNUMzNy4xLDI1LjgsMzYsMjcuNywzNC4xLDI4LjJ6ICAgIE0zMi44LDIzLjJjLTAuOSwwLjItMS40LDEuMS0xLjEsMmMwLjIsMC45LDEuMSwxLjQsMiwxLjFjMC45LTAuMiwxLjQtMS4xLDEuMS0yQzM0LjUsMjMuNSwzMy42LDIzLDMyLjgsMjMuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMjQuMiwyMy41Yy0xLjksMC41LTMuOC0wLjYtNC4zLTIuNXMwLjYtMy44LDIuNS00LjNzMy44LDAuNiw0LjMsMi41UzI2LjEsMjMsMjQuMiwyMy41eiBNMjIuOSwxOC42ICAgYy0wLjksMC4yLTEuNCwxLjEtMS4xLDJjMC4yLDAuOSwxLjEsMS40LDIsMS4xYzAuOS0wLjIsMS40LTEuMSwxLjEtMkMyNC43LDE4LjgsMjMuOCwxOC4zLDIyLjksMTguNnoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q1IiBmaWxsLW9wYWNpdHk9IjAiIGQ9Ik0yNi41LDUxLjVjMTMuOCwwLDI1LTExLjIsMjUtMjVzLTExLjItMjUtMjUtMjVzLTI1LDExLjItMjUsMjVTMTIuNyw1MS41LDI2LjUsNTEuNXoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuMywyMWgxMGMwLjQsMCwwLjgtMC4zLDAuOC0wLjhzLTAuMy0wLjgtMC44LTAuOGgtMTBDMzMuMywyMC4yLDMzLjMsMjAuMiwzMy4zLDIxeiIvPg0KICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICA8Y2lyY2xlIGNsYXNzPSJzdDYiIGZpbGwtb3BhY2l0eT0iMCIgY3g9IjIzLjMiIGN5PSIyMC4xIiByPSIyLjUiLz4NCiAgICAgICAgICAgICAgIDxjaXJjbGUgY2xhc3M9InN0NiIgZmlsbC1vcGFjaXR5PSIwIiBjeD0iMzMuMiIgY3k9IjI0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPGNpcmNsZSBjbGFzcz0ic3Q2IiBmaWxsLW9wYWNpdHk9IjAiIGN4PSIyMyIgY3k9IjM0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPC9zdmc+) no-repeat;
880 background-size: auto;
881 background-size: contain;
882 display: inline-block;
883 width: 28px;
884 height: 28px;
885 margin-bottom: -5px;
886 }
887
888 .elementor-navigator__element-widget .wpc-fe-icon {
889 width: 15px;
890 height: 15px;
891 margin-bottom: 0px;
892 }';
893 wp_add_inline_style( 'filter-everything-elementor', $css );
894 });
895
896 add_filter('elementor/document/wrapper_attributes', function($attributes) {
897 $attributes['wpc-filter-elementor-widget'] = true;
898 return $attributes;
899 });
900
901 add_action( 'wp_footer', function() {
902 if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
903 return;
904 }
905 if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){
906 if( flrt_get_experimental_option('disable_buttons') !== 'on' ) {
907
908 ?>
909
910 <script>
911 jQuery(function($) {
912 $(window).on('elementor/frontend/init', function() {
913 elementorFrontend.hooks.addAction(
914 'frontend/element_ready/filter-everything-filters.default',
915 function($scope) {
916 let $el = $('[wpc-filter-elementor-widget="1"][data-elementor-type]:not([data-elementor-type="loop-item"])');
917 if($el.length > 0){
918 $el.before(`<?php flrt_filters_button() ?>`);
919 }
920 }
921 );
922 });
923 });
924 </script>
925 <?php
926 }
927 }
928 });
929 }
930
931 add_action('admin_enqueue_scripts', function () {
932 $handle = 'filter-everything-menu-icon';
933 wp_register_style($handle, false);
934 wp_enqueue_style($handle);
935
936
937 $css = <<<PHP_CSS
938 #toplevel_page_edit-post_type-filter-set .wp-menu-image{
939 content: '';
940 background-repeat: no-repeat;
941 background-position: center;
942 background-size: 20px;
943 background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000142154616827085436530000012698217856111301567_);%7D .st3%7Bfill:%23a7aaad;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%23a7aaad;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%23a7aaad;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000111880200341027563210000003406718579453459379_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000111880200341027563210000003406718579453459379_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
944 }
945 #toplevel_page_edit-post_type-filter-set:hover .wp-menu-image{
946 background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000142154616827085436530000012698217856111301567_);%7D .st3%7Bfill:%2372AEE6;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%2372AEE6;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%2372AEE6;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000111880200341027563210000003406718579453459379_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000111880200341027563210000003406718579453459379_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
947 }
948 .wp-menu-open#toplevel_page_edit-post_type-filter-set .wp-menu-image {
949 background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000098199702249043298830000017010845528166695064_);%7D .st3%7Bfill:%23FFFFFF;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%23FFFFFF;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%23FFFFFF;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect x="0" y="0" class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000112608340804245442460000013986219178199086244_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000112608340804245442460000013986219178199086244_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
950 }
951 PHP_CSS;
952 wp_add_inline_style($handle, $css);
953 });
954
955 /**
956 * Fix Elementor query arguments for filtered content
957 *
958 * This function adjusts Elementor's query arguments when dealing with
959 * filtered content from Filter Everything Pro plugin. It ensures proper
960 * handling of custom post types in Elementor queries.
961 *
962 * @param array $query_args The Elementor query arguments
963 * @return array Modified query arguments
964 */
965 add_filter( 'elementor/query/get_query_args/current_query', 'flrt_fix_elementor_query_args' );
966 function flrt_fix_elementor_query_args( $query_args ) {
967 // Verify that we're dealing with a filtered query
968 if ( ! isset( $query_args['flrt_filtered_query'] ) || !$query_args['flrt_filtered_query'] ) {
969 return $query_args;
970 }
971
972 // Get post type from query args or current post
973 $post_type = isset( $query_args['post_type'] ) ? $query_args['post_type'] : get_post_type();
974
975 // Sanitize the post type
976 if ( ! empty( $post_type ) ) {
977 $post_type = sanitize_text_field( $post_type );
978 }
979
980 // Check if the post type is non-built-in
981 $post_type_object = get_post_type_object( $post_type );
982
983 if ( $post_type_object && !$post_type_object->_builtin ) {
984 // Remove taxonomy from query args if present
985 if ( isset( $query_args['taxonomy'] ) ) {
986 unset( $query_args['taxonomy'] );
987 }
988 }
989
990 return $query_args;
991 }
992
993 /**
994 * Fixes Elementor featured products price range query arguments.
995 *
996 * This function addresses an issue where Elementor's featured products widget
997 * incorrectly applies meta_key filtering when sorting by price, which can
998 * interfere with price range filtering functionality. It removes the meta_key
999 * from query arguments for featured products sorted by price.
1000 *
1001 *
1002 * @param array $query_args Query arguments for Elementor widget.
1003 * @param object $widget The Elementor widget instance.
1004 * @return array Modified query arguments.
1005 */
1006 if ( flrt_is_elementor_active() ) {
1007 add_filter( 'elementor/query/query_args', 'flrt_fix_elementor_featured_products_price_range', 10, 2 );
1008
1009 function flrt_fix_elementor_featured_products_price_range( array $query_args, $widget ): array {
1010 $is_featured = ( $query_args['post_type'] ?? '' ) === 'featured';
1011 $is_price_order = ( $query_args['orderby'] ?? '' ) === 'price';
1012
1013 if ( $is_featured && $is_price_order ) {
1014 static $registered = false;
1015
1016 if ( ! $registered ) {
1017 add_filter( 'elementor/query/query_args', function ( array $query_args, $widget ): array {
1018 unset( $query_args['meta_key'] );
1019 return $query_args;
1020 }, 11, 2 );
1021
1022 $registered = true;
1023 }
1024 }
1025
1026 return $query_args;
1027 }
1028 }
1029
1030
1031
1032 function flrt_is_divi_theme()
1033 {
1034 if ( 'Divi' === wp_get_theme()->get('Name') || 'Divi' === wp_get_theme()->get_template() ) {
1035 return true;
1036 }
1037 return false;
1038 }
1039
1040 if ( flrt_is_divi_theme() ) {
1041
1042 function wpc_initialize_divi_custom_module() {
1043 if (!class_exists('ET_Builder_Module')) {
1044 return;
1045 }
1046
1047 flrt_include('src/Admin/Widgets/DiviWidgets/ChipsDiviWidget.php');
1048 flrt_include('src/Admin/Widgets/DiviWidgets/FiltersDiviWidget.php');
1049 flrt_include('src/Admin/Widgets/DiviWidgets/SortingDiviWidget.php');
1050 }
1051
1052 add_action('et_builder_ready', 'wpc_initialize_divi_custom_module');
1053
1054 add_filter( 'et_builder_inner_content_class', function ($classes){
1055 $classes[] = 'wpc-divi-inner-content';
1056 return $classes;
1057 }, 10 );
1058
1059 if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ) {
1060 if (flrt_get_experimental_option('disable_buttons') !== 'on') {
1061 add_action('et_before_main_content', 'flrt_divi_filter_button');
1062 }
1063 }
1064 }
1065
1066 function flrt_divi_filter_button()
1067 {
1068 // et_before_main_content fires more than once per page when a Divi Theme
1069 // Builder header layout is present (both header.php and
1070 // theme-after-header.php do_action it), so nothing here may declare a
1071 // function at runtime — the previous nested declaration fataled with
1072 // "Cannot redeclare modify_specific_module" on the second call.
1073 // Re-adding the same filter callback is a no-op in WordPress.
1074 add_filter('et_module_process_display_conditions', 'flrt_divi_modify_specific_module', 10, 3);
1075 }
1076
1077 function flrt_divi_modify_specific_module($output, $render_slug, $module)
1078 {
1079 if ($module->slug === 'filter_everything') {
1080 flrt_filters_button(0, '', 'et_before_main_content');
1081 }
1082 return $output;
1083 }
1084 /**
1085 * Checks if the Breakdance plugin and its required classes/functions are active and exist.
1086 *
1087 * This function verifies the presence of the Breakdance plugin, along with specific
1088 * classes and functions used by the plugin. It returns true only if all checks pass,
1089 * indicating that Breakdance is properly installed and functional.
1090 *
1091 * @return bool True if Breakdance is active and its required components exist, false otherwise.
1092 */
1093 function flrt_check_breakdance() {
1094 if (!is_plugin_active('breakdance/plugin.php')) {
1095 return false;
1096 }
1097
1098 if (!function_exists('Breakdance\Util\getDirectoryPathRelativeToPluginFolder')) {
1099 return false;
1100 }
1101
1102 return true;
1103 }
1104 if(flrt_check_breakdance()){
1105 function flrt_breakdance_custom_css() {
1106 echo '<style>
1107 .breakdance-add-panel__element{
1108 background: #0A2D48;
1109 }
1110 </style>';
1111 }
1112 add_action('wp_head', 'flrt_breakdance_custom_css');
1113 flrt_include('src/Admin/Widgets/breakdance/widgets/breakdance.php');
1114 }
1115
1116 /**
1117 * Checks if Bricks Builder theme and its classes are ready to register custom elements.
1118 *
1119 * @return bool True if Bricks Builder theme is active and necessary classes exist, false otherwise.
1120 */
1121 function flrt_is_bricks_ready_for_elements() {
1122 $theme = wp_get_theme();
1123
1124 if (
1125 $theme->get_stylesheet() !== 'bricks' &&
1126 $theme->get_template() !== 'bricks'
1127 ) {
1128 return false;
1129 }
1130
1131 if ( ! class_exists( '\Bricks\Elements' ) ) {
1132 return false;
1133 }
1134
1135 if ( ! method_exists( '\Bricks\Elements', 'register_element' ) ) {
1136 return false;
1137 }
1138
1139 return true;
1140 }
1141
1142 /**
1143 * Registers custom Bricks elements during WordPress initialization.
1144 *
1145 * This function checks if Bricks Builder is ready using flrt_is_bricks_ready_for_elements().
1146 * If it is, it includes the ChipsBricksWidget.php file and registers the element using Bricks\Elements::register_element().
1147 */
1148
1149 add_action('init', 'flrt_init_bricks_widgets', 11);
1150
1151 function flrt_init_bricks_widgets() {
1152 if (flrt_is_bricks_ready_for_elements()) {
1153 $element_files = [
1154 FLRT_PLUGIN_DIR_PATH .'src/Admin/Widgets/bricks/ChipsBricksWidget.php',
1155 FLRT_PLUGIN_DIR_PATH .'src/Admin/Widgets/bricks/FiltersBricksWidget.php',
1156 FLRT_PLUGIN_DIR_PATH .'src/Admin/Widgets/bricks/SortingBricksWidget.php',
1157 ];
1158 foreach ($element_files as $file) {
1159 \Bricks\Elements::register_element($file);
1160 }
1161
1162 add_filter( 'bricks/builder/i18n', function( $i18n ) {
1163 $i18n['filter-everything'] = esc_html__( 'Filter Everything', 'filter-everything' );
1164 return $i18n;
1165 } );
1166
1167 function flrt_bricks_custom_css() {
1168 echo '<style>
1169 .wpc-fe-icon {
1170 background: var(--builder-color);
1171 mask-image: url(' . flrt_get_icon_logo_svg_css() . ');
1172 mask-repeat: no-repeat;
1173 mask-size: contain;
1174 display: inline-block;
1175 width: 28px;
1176 height: 28px;
1177 margin-bottom: -5px;
1178 }
1179
1180 .bricks-add-element:focus .wpc-fe-icon, .bricks-add-element:hover .wpc-fe-icon {
1181 background: var(--builder-color-accent);
1182 }
1183
1184 .structure-item .wpc-fe-icon {
1185 width: 16px;
1186 height: 16px;
1187 margin-bottom: 0px;
1188 }
1189 </style>';
1190 }
1191 add_action('wp_head', 'flrt_bricks_custom_css');
1192 }
1193 }
1194
1195 function wpc_beaver_builder_widgets_load() {
1196 if ( class_exists( 'FLBuilder' ) ) {
1197 flrt_include('src/Admin/Widgets/beaver/chips/ChipsBeaverWidget.php');
1198 flrt_include('src/Admin/Widgets/beaver/filters/FiltersBeaverWidget.php');
1199 flrt_include('src/Admin/Widgets/beaver/sorting/SortingBeaverWidget.php');
1200 }
1201 }
1202 add_action( 'init', 'wpc_beaver_builder_widgets_load' );
1203
1204 /**
1205 * XStore theme — "Display variable products as single variations" compatibility.
1206 *
1207 * With that XStore option (variable_products_detach) the theme:
1208 * 1. adds 'product_variation' to the shop query's post_type, hides variable
1209 * parents via post__not_in and flags the query with single_variations_filter=yes;
1210 * 2. on posts_clauses (priority 20) appends a TOP-LEVEL
1211 * "OR ( post_type='product_variation' AND post_status='publish' AND … )"
1212 * branch, re-implementing WooCommerce's own layered-nav filters for the
1213 * detached variations (price, rating, brand, chosen attributes from $_GET).
1214 *
1215 * The theme knows nothing about Filter Everything, so on FE-filtered pages that
1216 * OR branch let EVERY published variation into the results, past FE's term
1217 * constraints — filtering visually "did nothing" (each alternative of a
1218 * top-level OR must repeat the filter conditions).
1219 *
1220 * Fix: append FE's active filter constraints AFTER the theme's branch
1221 * (priority 30). AND binds tighter than OR, so in
1222 * <first alternative> OR ( <theme branch> ) AND ( <FE constraints> )
1223 * the constraints apply to the variations branch only, leaving the first
1224 * alternative (already filtered by FE the regular way) untouched.
1225 */
1226 function flrt_xstore_detached_variations_where( $clauses, $wp_query ) {
1227 global $wpdb;
1228
1229 if ( is_admin() || empty( $clauses['where'] ) ) {
1230 return $clauses;
1231 }
1232
1233 // Only XStore "detached variations" queries that FE has actually filtered.
1234 if ( $wp_query->get( 'single_variations_filter' ) !== 'yes' || ! $wp_query->get( 'flrt_filtered_query' ) ) {
1235 return $clauses;
1236 }
1237
1238 // The theme adds its branch at priority 20 — bail if it is not there.
1239 if ( strpos( $clauses['where'], "OR ({$wpdb->posts}.post_type = 'product_variation'" ) === false ) {
1240 return $clauses;
1241 }
1242
1243 $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
1244 $queried_values = $wpManager->getQueryVar( 'queried_values' );
1245
1246 if ( empty( $queried_values ) || ! is_array( $queried_values ) ) {
1247 return $clauses;
1248 }
1249
1250 $conditions = [];
1251
1252 foreach ( $queried_values as $queried ) {
1253
1254 if ( ! isset( $queried['entity'], $queried['e_name'] ) ) {
1255 continue;
1256 }
1257
1258 // Taxonomy filters: a variation matches when its PARENT product carries
1259 // the term (variations have no term_relationships rows of their own).
1260 if ( $queried['entity'] === 'taxonomy' && ! empty( $queried['values'] ) ) {
1261 $tax = $queried['e_name'];
1262 $and_logic = ( isset( $queried['logic'] ) && $queried['logic'] === 'and' );
1263 $groups = []; // one ttid-group per condition: single for OR-logic, per-term for AND-logic
1264 $slugs = [];
1265
1266 foreach ( (array) $queried['values'] as $value_slug ) {
1267 $term = get_term_by( 'slug', $value_slug, $tax );
1268 if ( ! $term ) {
1269 continue;
1270 }
1271 $slugs[] = esc_sql( $term->slug );
1272
1273 $ttids = [ (int) $term->term_taxonomy_id ];
1274 if ( is_taxonomy_hierarchical( $tax ) && ! $and_logic ) {
1275 foreach ( get_term_children( $term->term_id, $tax ) as $child_id ) {
1276 $child = get_term( $child_id, $tax );
1277 if ( $child && ! is_wp_error( $child ) ) {
1278 $ttids[] = (int) $child->term_taxonomy_id;
1279 }
1280 }
1281 }
1282
1283 if ( $and_logic ) {
1284 $groups[] = $ttids; // every term required — own condition each
1285 } elseif ( empty( $groups ) ) {
1286 $groups[] = $ttids; // any term enough — collect into one IN()
1287 } else {
1288 $groups[0] = array_merge( $groups[0], $ttids );
1289 }
1290 }
1291
1292 if ( empty( $groups ) ) {
1293 continue;
1294 }
1295
1296 foreach ( $groups as $group_ttids ) {
1297 $ttids_in = implode( ',', array_unique( $group_ttids ) );
1298 $parent_has_term = "{$wpdb->posts}.post_parent IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ({$ttids_in}) )";
1299
1300 if ( strpos( $tax, 'pa_' ) === 0 && ! $and_logic && ! empty( $slugs ) ) {
1301 // Variation attributes: prefer the variation's own value —
1302 // a variation with a DIFFERENT value must not ride in on its
1303 // parent's term. Variations without own value ("Any …")
1304 // fall back to the parent's term.
1305 $meta_key = esc_sql( 'attribute_' . $tax );
1306 $slugs_in = "'" . implode( "','", $slugs ) . "'";
1307
1308 $conditions[] = "( {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value IN ({$slugs_in}) )"
1309 . " OR ( {$parent_has_term}"
1310 . " AND {$wpdb->posts}.ID NOT IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value <> '' ) ) )";
1311 } else {
1312 $conditions[] = $parent_has_term;
1313 }
1314 }
1315 }
1316
1317 // Numeric meta filters (price and alike): variations carry their own value.
1318 if ( $queried['entity'] === 'post_meta_num' && isset( $queried['values'] ) && is_array( $queried['values'] ) ) {
1319 $meta_key = esc_sql( $queried['e_name'] );
1320 $min = ( isset( $queried['values']['min'] ) && $queried['values']['min'] !== '' ) ? (float) $queried['values']['min'] : false;
1321 $max = ( isset( $queried['values']['max'] ) && $queried['values']['max'] !== '' ) ? (float) $queried['values']['max'] : false;
1322
1323 $range = [];
1324 if ( $min !== false ) {
1325 $range[] = "CAST(meta_value AS DECIMAL(15,6)) >= {$min}";
1326 }
1327 if ( $max !== false ) {
1328 $range[] = "CAST(meta_value AS DECIMAL(15,6)) <= {$max}";
1329 }
1330
1331 if ( $range ) {
1332 $conditions[] = "{$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND " . implode( ' AND ', $range ) . " )";
1333 }
1334 }
1335
1336 // Other filter entities (post_meta choices, author, post_date …) are not
1337 // mirrored into the variations branch yet — they are rare on shop archives.
1338 }
1339
1340 if ( ! empty( $conditions ) ) {
1341 $clauses['where'] .= ' AND ( ' . implode( ' ) AND ( ', $conditions ) . ' )';
1342 }
1343
1344 return $clauses;
1345 }
1346 add_filter( 'posts_clauses', 'flrt_xstore_detached_variations_where', 30, 2 );
1347
1348 //@todo check this with PLL support
1349 //function flrt_add_cpt_to_pll_tmp( $post_types, $is_settings ) {
1350 // if ( $is_settings ) {
1351 // $post_types[ FLRT_FILTERS_SET_POST_TYPE ] = FLRT_FILTERS_SET_POST_TYPE;
1352 // }
1353 // return $post_types;
1354 //}