| @@ -1,18 +1,26 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -if ( ! defined('WPINC') ) { | |
| 4 | - wp_die(); | |
| 3 | +if ( ! defined('ABSPATH') ) { | |
| 4 | + exit; | |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | 7 | function flrt_is_woocommerce() |
| 8 | 8 | { |
| 9 | - if( function_exists('is_woocommerce') ){ | |
| 10 | - return is_woocommerce(); | |
| 9 | + if( class_exists('WooCommerce') ){ | |
| 10 | + return true; | |
| 11 | 11 | } |
| 12 | 12 | return false; |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | +function flrt_is_acf() | |
| 16 | +{ | |
| 17 | + if( class_exists( 'ACF' ) ){ | |
| 18 | + return true; | |
| 19 | + } | |
| 20 | + return false; | |
| 21 | +} | |
| 22 | + | |
| 15 | 23 | function flrt_get_mobile_width(){ |
| 16 | 24 | return apply_filters( 'wpc_mobile_width', 768 ); |
| 17 | 25 | } |
| 18 | 26 | |
| @@ -24,19 +32,33 @@ | ||
| 24 | 32 | |
| 25 | 33 | function flrt_wp(){ |
| 26 | 34 | $theme_dependencies = flrt_get_theme_dependencies(); |
| 27 | 35 | |
| 28 | - if( flrt_get_option('show_bottom_widget') === 'on' ) { | |
| 36 | + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){ | |
| 29 | 37 | |
| 30 | 38 | if( flrt_get_experimental_option('disable_buttons') !== 'on' ) { |
| 31 | 39 | |
| 32 | - if (flrt_is_woocommerce()) { | |
| 33 | - add_action('woocommerce_before_shop_loop', 'flrt_filters_button', 5); | |
| 34 | - add_action('woocommerce_no_products_found', 'flrt_filters_button', 5); | |
| 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 | + | |
| 35 | 55 | } else { |
| 36 | 56 | if (isset($theme_dependencies['button_hook']) && is_array($theme_dependencies['button_hook'])) { |
| 37 | 57 | foreach ($theme_dependencies['button_hook'] as $button_hook) { |
| 38 | - add_action($button_hook, 'flrt_filters_button', 15); | |
| 58 | + add_action($button_hook, function() use ($button_hook) { | |
| 59 | + flrt_filters_button(0, '', $button_hook); | |
| 60 | + }, 15); | |
| 39 | 61 | } |
| 40 | 62 | } |
| 41 | 63 | } |
| 42 | 64 | } |
| @@ -43,15 +65,14 @@ | ||
| 43 | 65 | |
| 44 | 66 | } |
| 45 | 67 | |
| 46 | 68 | // Add selected terms to the top |
| 47 | - if( flrt_is_woocommerce() ) { | |
| 48 | - add_action('woocommerce_no_products_found', 'flrt_add_selected_terms_above_the_top'); | |
| 49 | - add_action('woocommerce_before_shop_loop', 'flrt_add_selected_terms_above_the_top', 5); | |
| 50 | - }else { | |
| 51 | - if (isset($theme_dependencies['chips_hook']) && is_array($theme_dependencies['chips_hook'])) { | |
| 52 | - foreach ($theme_dependencies['chips_hook'] as $chips_hook) { | |
| 53 | - add_action($chips_hook, 'flrt_add_selected_terms_above_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' ); | |
| 54 | 75 | } |
| 55 | 76 | } |
| 56 | 77 | } |
| 57 | 78 | } |
| @@ -63,11 +84,9 @@ | ||
| 63 | 84 | } |
| 64 | 85 | |
| 65 | 86 | function flrt_add_selected_terms_above_the_top() |
| 66 | 87 | { |
| 67 | - if( flrt_get_option( 'show_terms_in_content' ) === 'on' ){ | |
| 68 | - flrt_show_selected_terms(true); | |
| 69 | - } | |
| 88 | + flrt_show_selected_terms(true); | |
| 70 | 89 | } |
| 71 | 90 | |
| 72 | 91 | function flrt_get_theme_dependencies(){ |
| 73 | 92 | $current_theme = strtolower( get_template() ); |
| @@ -143,8 +162,15 @@ | ||
| 143 | 162 | 'primary_color' => '#0073aa', |
| 144 | 163 | 'button_hook' => '', |
| 145 | 164 | 'chips_hook' => '' |
| 146 | 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 | + ), | |
| 147 | 173 | 'twentytwenty' => array( |
| 148 | 174 | 'posts_container' => '#site-content', |
| 149 | 175 | 'sidebar_container' => '', |
| 150 | 176 | 'primary_color' => '#cd2653', |
| @@ -305,15 +331,30 @@ | ||
| 305 | 331 | 'primary_color' => '', |
| 306 | 332 | 'button_hook' => '', |
| 307 | 333 | 'chips_hook' => '' |
| 308 | 334 | ), |
| 309 | - 'divi' => array( | |
| 310 | - 'posts_container' => '#primary', | |
| 335 | + 'woodmart' => array( | |
| 336 | + 'posts_container' => '.site-content', | |
| 311 | 337 | 'sidebar_container' => '#secondary', |
| 312 | - 'primary_color' => '', | |
| 338 | + 'primary_color' => '#83b735', | |
| 313 | 339 | 'button_hook' => '', |
| 314 | - 'chips_hook' => '' | |
| 340 | + 'chips_hook' => array( 'woodmart_shop_filters_area', 'woodmart_main_loop') | |
| 315 | 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 | + ), | |
| 316 | 357 | ); |
| 317 | 358 | |
| 318 | 359 | $theme_dependencies = apply_filters( 'wpc_theme_dependencies', $theme_dependencies ); |
| 319 | 360 | |
| @@ -363,31 +404,979 @@ | ||
| 363 | 404 | add_filter('wpc_theme_posts_container', 'flrt_set_posts_container'); |
| 364 | 405 | |
| 365 | 406 | // Set correct theme color |
| 366 | 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 | + } | |
| 367 | 414 | } |
| 368 | 415 | } |
| 369 | 416 | add_action('init', 'flrt_init'); |
| 370 | 417 | |
| 371 | -add_filter( 'elementor/theme/posts_archive/query_posts/query_vars', 'flrt_fix_elementor_query_args' ); | |
| 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 | + /* | |
| 794 | + * $data_next_page carries the GET part of the current request, and | |
| 795 | + * getFormActionOrFullPageUrl() hands it back URL-DECODED (parse_str() | |
| 796 | + * + build_query(), which does not re-encode). Printed raw, a request | |
| 797 | + * like ?x="><script>… closed the attribute and injected markup — | |
| 798 | + * reflected XSS, reported by Wordfence (CVE-2026-87869). esc_url() | |
| 799 | + * drops the characters that can break out of the attribute and | |
| 800 | + * re-encodes the ampersands for the HTML context. | |
| 801 | + * A callback instead of a replacement string: in a string "$1" or | |
| 802 | + * "\1" coming from the URL would be read as a backreference. | |
| 803 | + */ | |
| 804 | + $next_page_attr = 'data-next-page="' . esc_url( $data_next_page ) . '"'; | |
| 805 | + $widget_content = preg_replace_callback( | |
| 806 | + '%data-next-page\="[^"]+"%', | |
| 807 | + function () use ( $next_page_attr ) { | |
| 808 | + return $next_page_attr; | |
| 809 | + }, | |
| 810 | + $widget_content | |
| 811 | + ); | |
| 812 | + } | |
| 813 | + | |
| 814 | + return $widget_content; | |
| 815 | +} | |
| 816 | + | |
| 817 | +add_filter( 'wpc_remove_pagination_base', 'flrt_remove_pagination_base' ); | |
| 818 | +function flrt_remove_pagination_base( $url ){ | |
| 819 | + global $wp_rewrite; | |
| 820 | + | |
| 821 | + $rewrite = $wp_rewrite->wp_rewrite_rules(); | |
| 822 | + $url = ( ! empty( $rewrite ) ) ? user_trailingslashit( $url ) : rtrim( $url, '/' ) . '/'; | |
| 823 | + | |
| 824 | + return $url; | |
| 825 | +} | |
| 826 | + | |
| 827 | +function flrt_is_woo_discount_rules() | |
| 828 | +{ | |
| 829 | + $check_woo_discount_rules = apply_filters('flrt_woo_discount_rules_enabled', true); | |
| 830 | + if(!$check_woo_discount_rules) return false; | |
| 831 | + if( flrt_is_woocommerce() && | |
| 832 | + class_exists('Wdr\App\Helpers\Woocommerce') && | |
| 833 | + class_exists('Wdr\App\Controllers\Base') && | |
| 834 | + class_exists('Wdr\App\Helpers\Rule') && | |
| 835 | + class_exists('Wdr\App\Controllers\ManageDiscount') && | |
| 836 | + class_exists('Wdr\App\Controllers\DiscountCalculator') && | |
| 837 | + class_exists('Wdr\App\Models\DBTable') | |
| 838 | + ) | |
| 839 | + { | |
| 840 | + $tb_table = new Wdr\App\Models\DBTable(); | |
| 841 | + $wdr_rules = $tb_table::getRules(); | |
| 842 | + if(!empty($wdr_rules)){ | |
| 843 | + $discount_types = []; | |
| 844 | + foreach ($wdr_rules as $rule){ | |
| 845 | + $discount_types[] = $rule->discount_type; | |
| 846 | + } | |
| 847 | + $allowed_discount_types = ['wdr_simple_discount', 'wdr_bulk_discount', 'wdr_set_discount']; | |
| 848 | + if(!empty(array_intersect($allowed_discount_types, $discount_types))){ | |
| 849 | + return true; | |
| 850 | + } | |
| 851 | + } | |
| 852 | + } | |
| 853 | + return false; | |
| 854 | +} | |
| 855 | + | |
| 856 | +function flrt_is_elementor_active() | |
| 857 | +{ | |
| 858 | + return did_action( 'elementor/loaded' ); | |
| 859 | +} | |
| 860 | + | |
| 861 | +if ( flrt_is_elementor_active() ) { | |
| 862 | + function wpc_add_elementor_widget_categories( $elements_manager ) { | |
| 863 | + $pro_text = (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO) | |
| 864 | + ? ' ' .esc_html__('PRO', 'filter-everything') | |
| 865 | + : ''; | |
| 866 | + | |
| 867 | + $elements_manager->add_category( | |
| 868 | + 'filter-everything', | |
| 869 | + [ | |
| 870 | + 'title' => esc_html__( 'Filter Everything', 'filter-everything' ) . $pro_text, | |
| 871 | + 'icon' => 'fa-solid fa-filter', | |
| 872 | + ] | |
| 873 | + ); | |
| 874 | + } | |
| 875 | + add_action( 'elementor/elements/categories_registered', 'wpc_add_elementor_widget_categories' ); | |
| 876 | + | |
| 877 | + function wpc_register_elementor_widget( $widgets_manager ) { | |
| 878 | + | |
| 879 | + flrt_include('src/Frontend/Builders/ElementorWidgets/ChipsElementorWidget.php'); | |
| 880 | + flrt_include('src/Frontend/Builders/ElementorWidgets/FiltersElementorWidget.php'); | |
| 881 | + flrt_include('src/Frontend/Builders/ElementorWidgets/SortingElementorWidget.php'); | |
| 882 | + | |
| 883 | + $widgets_manager->register( new \FilterEverything\Filter\ChipsElementorWidget() ); | |
| 884 | + $widgets_manager->register( new \FilterEverything\Filter\FiltersElementorWidget() ); | |
| 885 | + $widgets_manager->register( new \FilterEverything\Filter\SortingElementorWidget() ); | |
| 886 | + | |
| 887 | + } | |
| 888 | + add_action( 'elementor/widgets/register', 'wpc_register_elementor_widget' ); | |
| 889 | + | |
| 890 | + add_action( 'elementor/editor/after_enqueue_styles', function() { | |
| 891 | + wp_enqueue_style( | |
| 892 | + 'filter-everything-elementor', | |
| 893 | + FLRT_PLUGIN_DIR_URL . 'assets/css/elementor-icon.css' | |
| 894 | + ); | |
| 895 | + $css = ' | |
| 896 | + .wpc-fe-icon { | |
| 897 | + background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUzIDUzIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA1MyA1MyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTMgNTM7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCiAgICAgICAgICAgICAgIDxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQogICAgICAgICAgICAgICAgLnN0MHtkaXNwbGF5Om5vbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDF7ZGlzcGxheTppbmxpbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDN7ZmlsbDojZmZmZmZmO30NCiAgICAgICAgICAgICAgICAuc3Q0e2Rpc3BsYXk6bm9uZTtmaWxsOiNmZmZmZmY7fQ0KICAgICAgICAgICAgICAgIC5zdDV7ZmlsbDpub25lO2ZpbGwtb3BhY2l0eTowO3N0cm9rZTojZmZmZmZmO3N0cm9rZS13aWR0aDozO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCiAgICAgICAgICAgICAgICAuc3Q2e2ZpbGw6bm9uZTtmaWxsLW9wYWNpdHk6MDtzdHJva2U6I2ZmZmZmZjtzdHJva2Utd2lkdGg6MjtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQogICAgICAgICAgICAgICA8L3N0eWxlPg0KICAgICAgICAgICAgICAgPGcgaWQ9IkxheWVyXzJfMDAwMDAwNDc3NzA3MTk3MTAxMTA3NDIyMzAwMDAwMDM5MjM5NTE2MjYxNDg4NDk1NTdfIiBjbGFzcz0ic3QwIj4NCiAgICAgICAgICAgICAgICA8cmVjdCB4PSIwIiB5PSIwIiBjbGFzcz0ic3QxIiB3aWR0aD0iNTMuMSIgaGVpZ2h0PSI1My4xIi8+DQogICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICA8ZyBpZD0iTGF5ZXJfMV8wMDAwMDE2MjMzMzEwMzI2NTgwNjk4MTUzMDAwMDAxNzE0NjYyNDI0NzU5MTY3NDU1Nl8iPg0KICAgICAgICAgICAgICAgIDxnPg0KICAgICAgICAgICAgICAgICAgIDxkZWZzPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGlkPSJTVkdJRF8xXyIgZD0iTTAsMGg1M3Y1M0gwVjB6IE0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNSAgICAgQzIwLjgsMzYuMSwyMS45LDM3LjIsMjMuMywzNy4yeiBNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6ICAgICAgTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgICAgPC9kZWZzPg0KICAgICAgICAgICAgICAgICAgIDxjbGlwUGF0aCBpZD0iU1ZHSURfMDAwMDAxMTI2MDgzNDA4MDQyNDU0NDI0NjAwMDAwMTM5ODYyMTkxNzgxOTkwODYyNDRfIj4NCiAgICAgICAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNTVkdJRF8xXyIgc3R5bGU9Im92ZXJmbG93OnZpc2libGU7Ii8+DQogICAgICAgICAgICAgICAgICAgPC9jbGlwUGF0aD4NCiAgICAgICAgICAgICAgICAgICA8ZyBpZD0iQmFyc0NsaXBwZWQiIHN0eWxlPSJjbGlwLXBhdGg6dXJsKCNTVkdJRF8wMDAwMDExMjYwODM0MDgwNDI0NTQ0MjQ2MDAwMDAxMzk4NjIxOTE3ODE5OTA4NjI0NF8pOyI+DQogICAgICAgICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0MyIgZD0iTTM5LjksMzEuNUwxOCwzNy4zYy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEM0MC44LDMwLjcsNDAuNSwzMS4zLDM5LjksMzEuNXoiLz4NCiAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMzguMSwyNC42bC0yMS45LDUuOWMtMC42LDAuMi0xLjItMC4yLTEuNC0wLjhjLTAuMi0wLjYsMC4yLTEuMiwwLjgtMS40bDIxLjktNS45YzAuNi0wLjIsMS4yLDAuMiwxLjQsMC44ICAgICBDMzksMjMuOCwzOC43LDI0LjUsMzguMSwyNC42eiIvPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zNi4yLDE3LjlsLTIxLjksNS45Yy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEMzNy4yLDE3LjEsMzYuOCwxNy43LDM2LjIsMTcuOXoiLz4NCiAgICAgICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNUMyMC44LDM2LjEsMjEuOSwzNy4yLDIzLjMsMzcuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLjksMzguMmMtMS45LDAuNS0zLjgtMC42LTQuMy0yLjVjLTAuNS0xLjksMC42LTMuOCwyLjUtNC4zczMuOCwwLjYsNC4zLDIuNUMyNi45LDM1LjgsMjUuOCwzNy43LDIzLjksMzguMiAgIHogTTIyLjYsMzMuMmMtMC45LDAuMi0xLjQsMS4xLTEuMSwyYzAuMiwwLjksMS4xLDEuNCwyLDEuMWMwLjktMC4yLDEuNC0xLjEsMS4xLTJDMjQuMywzMy41LDIzLjQsMzMsMjIuNiwzMy4yeiIvPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0zNC4xLDI4LjJjLTEuOSwwLjUtMy44LTAuNi00LjMtMi41czAuNi0zLjgsMi41LTQuM2MxLjktMC41LDMuOCwwLjYsNC4zLDIuNUMzNy4xLDI1LjgsMzYsMjcuNywzNC4xLDI4LjJ6ICAgIE0zMi44LDIzLjJjLTAuOSwwLjItMS40LDEuMS0xLjEsMmMwLjIsMC45LDEuMSwxLjQsMiwxLjFjMC45LTAuMiwxLjQtMS4xLDEuMS0yQzM0LjUsMjMuNSwzMy42LDIzLDMyLjgsMjMuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMjQuMiwyMy41Yy0xLjksMC41LTMuOC0wLjYtNC4zLTIuNXMwLjYtMy44LDIuNS00LjNzMy44LDAuNiw0LjMsMi41UzI2LjEsMjMsMjQuMiwyMy41eiBNMjIuOSwxOC42ICAgYy0wLjksMC4yLTEuNCwxLjEtMS4xLDJjMC4yLDAuOSwxLjEsMS40LDIsMS4xYzAuOS0wLjIsMS40LTEuMSwxLjEtMkMyNC43LDE4LjgsMjMuOCwxOC4zLDIyLjksMTguNnoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q1IiBmaWxsLW9wYWNpdHk9IjAiIGQ9Ik0yNi41LDUxLjVjMTMuOCwwLDI1LTExLjIsMjUtMjVzLTExLjItMjUtMjUtMjVzLTI1LDExLjItMjUsMjVTMTIuNyw1MS41LDI2LjUsNTEuNXoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuMywyMWgxMGMwLjQsMCwwLjgtMC4zLDAuOC0wLjhzLTAuMy0wLjgtMC44LTAuOGgtMTBDMzMuMywyMC4yLDMzLjMsMjAuMiwzMy4zLDIxeiIvPg0KICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICA8Y2lyY2xlIGNsYXNzPSJzdDYiIGZpbGwtb3BhY2l0eT0iMCIgY3g9IjIzLjMiIGN5PSIyMC4xIiByPSIyLjUiLz4NCiAgICAgICAgICAgICAgIDxjaXJjbGUgY2xhc3M9InN0NiIgZmlsbC1vcGFjaXR5PSIwIiBjeD0iMzMuMiIgY3k9IjI0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPGNpcmNsZSBjbGFzcz0ic3Q2IiBmaWxsLW9wYWNpdHk9IjAiIGN4PSIyMyIgY3k9IjM0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPC9zdmc+) no-repeat; | |
| 898 | + background-size: auto; | |
| 899 | + background-size: contain; | |
| 900 | + display: inline-block; | |
| 901 | + width: 28px; | |
| 902 | + height: 28px; | |
| 903 | + margin-bottom: -5px; | |
| 904 | + } | |
| 905 | + | |
| 906 | + .elementor-navigator__element-widget .wpc-fe-icon { | |
| 907 | + width: 15px; | |
| 908 | + height: 15px; | |
| 909 | + margin-bottom: 0px; | |
| 910 | + }'; | |
| 911 | + wp_add_inline_style( 'filter-everything-elementor', $css ); | |
| 912 | + }); | |
| 913 | + | |
| 914 | + add_filter('elementor/document/wrapper_attributes', function($attributes) { | |
| 915 | + $attributes['wpc-filter-elementor-widget'] = true; | |
| 916 | + return $attributes; | |
| 917 | + }); | |
| 918 | + | |
| 919 | + add_action( 'wp_footer', function() { | |
| 920 | + if ( ! defined( 'ELEMENTOR_VERSION' ) ) { | |
| 921 | + return; | |
| 922 | + } | |
| 923 | + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){ | |
| 924 | + if( flrt_get_experimental_option('disable_buttons') !== 'on' ) { | |
| 925 | + | |
| 926 | + ?> | |
| 927 | + | |
| 928 | + <script> | |
| 929 | + jQuery(function($) { | |
| 930 | + $(window).on('elementor/frontend/init', function() { | |
| 931 | + elementorFrontend.hooks.addAction( | |
| 932 | + 'frontend/element_ready/filter-everything-filters.default', | |
| 933 | + function($scope) { | |
| 934 | + let $el = $('[wpc-filter-elementor-widget="1"][data-elementor-type]:not([data-elementor-type="loop-item"])'); | |
| 935 | + if($el.length > 0){ | |
| 936 | + $el.before(`<?php flrt_filters_button() ?>`); | |
| 937 | + } | |
| 938 | + } | |
| 939 | + ); | |
| 940 | + }); | |
| 941 | + }); | |
| 942 | + </script> | |
| 943 | + <?php | |
| 944 | + } | |
| 945 | + } | |
| 946 | + }); | |
| 947 | +} | |
| 948 | + | |
| 949 | +add_action('admin_enqueue_scripts', function () { | |
| 950 | + $handle = 'filter-everything-menu-icon'; | |
| 951 | + wp_register_style($handle, false); | |
| 952 | + wp_enqueue_style($handle); | |
| 953 | + | |
| 954 | + | |
| 955 | + $css = <<<PHP_CSS | |
| 956 | + #toplevel_page_edit-post_type-filter-set .wp-menu-image{ | |
| 957 | + content: ''; | |
| 958 | + background-repeat: no-repeat; | |
| 959 | + background-position: center; | |
| 960 | + background-size: 20px; | |
| 961 | + 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'); | |
| 962 | + } | |
| 963 | + #toplevel_page_edit-post_type-filter-set:hover .wp-menu-image{ | |
| 964 | + 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'); | |
| 965 | + } | |
| 966 | + .wp-menu-open#toplevel_page_edit-post_type-filter-set .wp-menu-image { | |
| 967 | + 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'); | |
| 968 | + } | |
| 969 | + PHP_CSS; | |
| 970 | + wp_add_inline_style($handle, $css); | |
| 971 | +}); | |
| 972 | + | |
| 973 | +/** | |
| 974 | + * Fix Elementor query arguments for filtered content | |
| 975 | + * | |
| 976 | + * This function adjusts Elementor's query arguments when dealing with | |
| 977 | + * filtered content from Filter Everything Pro plugin. It ensures proper | |
| 978 | + * handling of custom post types in Elementor queries. | |
| 979 | + * | |
| 980 | + * @param array $query_args The Elementor query arguments | |
| 981 | + * @return array Modified query arguments | |
| 982 | + */ | |
| 372 | 983 | add_filter( 'elementor/query/get_query_args/current_query', 'flrt_fix_elementor_query_args' ); |
| 373 | -function flrt_fix_elementor_query_args( $query_args ){ | |
| 374 | - $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager(); | |
| 375 | - if( ! $wpManager->getQueryVar( 'allowed_filter_page' ) ){ | |
| 984 | +function flrt_fix_elementor_query_args( $query_args ) { | |
| 985 | + // Verify that we're dealing with a filtered query | |
| 986 | + if ( ! isset( $query_args['flrt_filtered_query'] ) || !$query_args['flrt_filtered_query'] ) { | |
| 376 | 987 | return $query_args; |
| 377 | 988 | } |
| 378 | 989 | |
| 379 | - if( isset( $query_args['taxonomy'] ) ){ | |
| 380 | - unset( $query_args['taxonomy'] ); | |
| 381 | - unset( $query_args['term'] ); | |
| 990 | + // Get post type from query args or current post | |
| 991 | + $post_type = isset( $query_args['post_type'] ) ? $query_args['post_type'] : get_post_type(); | |
| 992 | + | |
| 993 | + // Sanitize the post type | |
| 994 | + if ( ! empty( $post_type ) ) { | |
| 995 | + $post_type = sanitize_text_field( $post_type ); | |
| 382 | 996 | } |
| 383 | 997 | |
| 998 | + // Check if the post type is non-built-in | |
| 999 | + $post_type_object = get_post_type_object( $post_type ); | |
| 1000 | + | |
| 1001 | + if ( $post_type_object && !$post_type_object->_builtin ) { | |
| 1002 | + // Remove taxonomy from query args if present | |
| 1003 | + if ( isset( $query_args['taxonomy'] ) ) { | |
| 1004 | + unset( $query_args['taxonomy'] ); | |
| 1005 | + } | |
| 1006 | + } | |
| 1007 | + | |
| 384 | 1008 | return $query_args; |
| 385 | 1009 | } |
| 386 | 1010 | |
| 387 | -function flrt_wpml_active(){ | |
| 388 | - if ( function_exists('icl_object_id') ) { | |
| 1011 | +/** | |
| 1012 | + * Fixes Elementor featured products price range query arguments. | |
| 1013 | + * | |
| 1014 | + * This function addresses an issue where Elementor's featured products widget | |
| 1015 | + * incorrectly applies meta_key filtering when sorting by price, which can | |
| 1016 | + * interfere with price range filtering functionality. It removes the meta_key | |
| 1017 | + * from query arguments for featured products sorted by price. | |
| 1018 | + * | |
| 1019 | + * | |
| 1020 | + * @param array $query_args Query arguments for Elementor widget. | |
| 1021 | + * @param object $widget The Elementor widget instance. | |
| 1022 | + * @return array Modified query arguments. | |
| 1023 | + */ | |
| 1024 | +if ( flrt_is_elementor_active() ) { | |
| 1025 | + add_filter( 'elementor/query/query_args', 'flrt_fix_elementor_featured_products_price_range', 10, 2 ); | |
| 1026 | + | |
| 1027 | + function flrt_fix_elementor_featured_products_price_range( array $query_args, $widget ): array { | |
| 1028 | + $is_featured = ( $query_args['post_type'] ?? '' ) === 'featured'; | |
| 1029 | + $is_price_order = ( $query_args['orderby'] ?? '' ) === 'price'; | |
| 1030 | + | |
| 1031 | + if ( $is_featured && $is_price_order ) { | |
| 1032 | + static $registered = false; | |
| 1033 | + | |
| 1034 | + if ( ! $registered ) { | |
| 1035 | + add_filter( 'elementor/query/query_args', function ( array $query_args, $widget ): array { | |
| 1036 | + unset( $query_args['meta_key'] ); | |
| 1037 | + return $query_args; | |
| 1038 | + }, 11, 2 ); | |
| 1039 | + | |
| 1040 | + $registered = true; | |
| 1041 | + } | |
| 1042 | + } | |
| 1043 | + | |
| 1044 | + return $query_args; | |
| 1045 | + } | |
| 1046 | +} | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | +function flrt_is_divi_theme() | |
| 1051 | +{ | |
| 1052 | + if ( 'Divi' === wp_get_theme()->get('Name') || 'Divi' === wp_get_theme()->get_template() ) { | |
| 389 | 1053 | return true; |
| 390 | 1054 | } |
| 1055 | + return false; | |
| 1056 | +} | |
| 391 | 1057 | |
| 392 | - return false; | |
| 393 | -} | |
| 1058 | +if ( flrt_is_divi_theme() ) { | |
| 1059 | + | |
| 1060 | + function wpc_initialize_divi_custom_module() { | |
| 1061 | + if (!class_exists('ET_Builder_Module')) { | |
| 1062 | + return; | |
| 1063 | + } | |
| 1064 | + | |
| 1065 | + flrt_include('src/Frontend/Builders/DiviWidgets/ChipsDiviWidget.php'); | |
| 1066 | + flrt_include('src/Frontend/Builders/DiviWidgets/FiltersDiviWidget.php'); | |
| 1067 | + flrt_include('src/Frontend/Builders/DiviWidgets/SortingDiviWidget.php'); | |
| 1068 | + } | |
| 1069 | + | |
| 1070 | + add_action('et_builder_ready', 'wpc_initialize_divi_custom_module'); | |
| 1071 | + | |
| 1072 | + add_filter( 'et_builder_inner_content_class', function ($classes){ | |
| 1073 | + $classes[] = 'wpc-divi-inner-content'; | |
| 1074 | + return $classes; | |
| 1075 | + }, 10 ); | |
| 1076 | + | |
| 1077 | + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ) { | |
| 1078 | + if (flrt_get_experimental_option('disable_buttons') !== 'on') { | |
| 1079 | + add_action('et_before_main_content', 'flrt_divi_filter_button'); | |
| 1080 | + } | |
| 1081 | + } | |
| 1082 | +} | |
| 1083 | + | |
| 1084 | +function flrt_divi_filter_button() | |
| 1085 | +{ | |
| 1086 | + // et_before_main_content fires more than once per page when a Divi Theme | |
| 1087 | + // Builder header layout is present (both header.php and | |
| 1088 | + // theme-after-header.php do_action it), so nothing here may declare a | |
| 1089 | + // function at runtime — the previous nested declaration fataled with | |
| 1090 | + // "Cannot redeclare modify_specific_module" on the second call. | |
| 1091 | + // Re-adding the same filter callback is a no-op in WordPress. | |
| 1092 | + add_filter('et_module_process_display_conditions', 'flrt_divi_modify_specific_module', 10, 3); | |
| 1093 | +} | |
| 1094 | + | |
| 1095 | +function flrt_divi_modify_specific_module($output, $render_slug, $module) | |
| 1096 | +{ | |
| 1097 | + if ($module->slug === 'filter_everything') { | |
| 1098 | + flrt_filters_button(0, '', 'et_before_main_content'); | |
| 1099 | + } | |
| 1100 | + return $output; | |
| 1101 | +} | |
| 1102 | +/** | |
| 1103 | + * Checks if the Breakdance plugin and its required classes/functions are active and exist. | |
| 1104 | + * | |
| 1105 | + * This function verifies the presence of the Breakdance plugin, along with specific | |
| 1106 | + * classes and functions used by the plugin. It returns true only if all checks pass, | |
| 1107 | + * indicating that Breakdance is properly installed and functional. | |
| 1108 | + * | |
| 1109 | + * @return bool True if Breakdance is active and its required components exist, false otherwise. | |
| 1110 | + */ | |
| 1111 | +function flrt_check_breakdance() { | |
| 1112 | + // is_plugin_active() lives in wp-admin/includes/plugin.php and is not loaded | |
| 1113 | + // on the frontend, in WP-CLI or in cron. Fall back to the raw option list. | |
| 1114 | + if ( ! function_exists( 'is_plugin_active' ) ) { | |
| 1115 | + $active = (array) get_option( 'active_plugins', [] ); | |
| 1116 | + if ( is_multisite() ) { | |
| 1117 | + $active = array_merge( $active, array_keys( (array) get_site_option( 'active_sitewide_plugins', [] ) ) ); | |
| 1118 | + } | |
| 1119 | + if ( ! in_array( 'breakdance/plugin.php', $active, true ) ) { | |
| 1120 | + return false; | |
| 1121 | + } | |
| 1122 | + } elseif ( ! is_plugin_active( 'breakdance/plugin.php' ) ) { | |
| 1123 | + return false; | |
| 1124 | + } | |
| 1125 | + | |
| 1126 | + if (!function_exists('Breakdance\Util\getDirectoryPathRelativeToPluginFolder')) { | |
| 1127 | + return false; | |
| 1128 | + } | |
| 1129 | + | |
| 1130 | + return true; | |
| 1131 | +} | |
| 1132 | +if(flrt_check_breakdance()){ | |
| 1133 | + function flrt_breakdance_custom_css() { | |
| 1134 | + echo '<style> | |
| 1135 | + .breakdance-add-panel__element{ | |
| 1136 | + background: #0A2D48; | |
| 1137 | + } | |
| 1138 | + </style>'; | |
| 1139 | + } | |
| 1140 | + add_action('wp_head', 'flrt_breakdance_custom_css'); | |
| 1141 | + flrt_include('src/Frontend/Builders/breakdance/widgets/breakdance.php'); | |
| 1142 | +} | |
| 1143 | + | |
| 1144 | +/** | |
| 1145 | + * Checks if Bricks Builder theme and its classes are ready to register custom elements. | |
| 1146 | + * | |
| 1147 | + * @return bool True if Bricks Builder theme is active and necessary classes exist, false otherwise. | |
| 1148 | + */ | |
| 1149 | +function flrt_is_bricks_ready_for_elements() { | |
| 1150 | + $theme = wp_get_theme(); | |
| 1151 | + | |
| 1152 | + if ( | |
| 1153 | + $theme->get_stylesheet() !== 'bricks' && | |
| 1154 | + $theme->get_template() !== 'bricks' | |
| 1155 | + ) { | |
| 1156 | + return false; | |
| 1157 | + } | |
| 1158 | + | |
| 1159 | + if ( ! class_exists( '\Bricks\Elements' ) ) { | |
| 1160 | + return false; | |
| 1161 | + } | |
| 1162 | + | |
| 1163 | + if ( ! method_exists( '\Bricks\Elements', 'register_element' ) ) { | |
| 1164 | + return false; | |
| 1165 | + } | |
| 1166 | + | |
| 1167 | + return true; | |
| 1168 | +} | |
| 1169 | + | |
| 1170 | +/** | |
| 1171 | + * Registers custom Bricks elements during WordPress initialization. | |
| 1172 | + * | |
| 1173 | + * This function checks if Bricks Builder is ready using flrt_is_bricks_ready_for_elements(). | |
| 1174 | + * If it is, it includes the ChipsBricksWidget.php file and registers the element using Bricks\Elements::register_element(). | |
| 1175 | + */ | |
| 1176 | + | |
| 1177 | +add_action('init', 'flrt_init_bricks_widgets', 11); | |
| 1178 | + | |
| 1179 | +function flrt_init_bricks_widgets() { | |
| 1180 | + if (flrt_is_bricks_ready_for_elements()) { | |
| 1181 | + $element_files = [ | |
| 1182 | + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/ChipsBricksWidget.php', | |
| 1183 | + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/FiltersBricksWidget.php', | |
| 1184 | + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/SortingBricksWidget.php', | |
| 1185 | + ]; | |
| 1186 | + foreach ($element_files as $file) { | |
| 1187 | + \Bricks\Elements::register_element($file); | |
| 1188 | + } | |
| 1189 | + | |
| 1190 | + add_filter( 'bricks/builder/i18n', function( $i18n ) { | |
| 1191 | + $i18n['filter-everything'] = esc_html__( 'Filter Everything', 'filter-everything' ); | |
| 1192 | + return $i18n; | |
| 1193 | + } ); | |
| 1194 | + | |
| 1195 | + function flrt_bricks_custom_css() { | |
| 1196 | + echo '<style> | |
| 1197 | + .wpc-fe-icon { | |
| 1198 | + background: var(--builder-color); | |
| 1199 | + mask-image: url(' . flrt_get_icon_logo_svg_css() . '); | |
| 1200 | + mask-repeat: no-repeat; | |
| 1201 | + mask-size: contain; | |
| 1202 | + display: inline-block; | |
| 1203 | + width: 28px; | |
| 1204 | + height: 28px; | |
| 1205 | + margin-bottom: -5px; | |
| 1206 | + } | |
| 1207 | + | |
| 1208 | + .bricks-add-element:focus .wpc-fe-icon, .bricks-add-element:hover .wpc-fe-icon { | |
| 1209 | + background: var(--builder-color-accent); | |
| 1210 | + } | |
| 1211 | + | |
| 1212 | + .structure-item .wpc-fe-icon { | |
| 1213 | + width: 16px; | |
| 1214 | + height: 16px; | |
| 1215 | + margin-bottom: 0px; | |
| 1216 | + } | |
| 1217 | + </style>'; | |
| 1218 | + } | |
| 1219 | + add_action('wp_head', 'flrt_bricks_custom_css'); | |
| 1220 | + } | |
| 1221 | +} | |
| 1222 | + | |
| 1223 | +function wpc_beaver_builder_widgets_load() { | |
| 1224 | + if ( class_exists( 'FLBuilder' ) ) { | |
| 1225 | + flrt_include('src/Frontend/Builders/beaver/chips/ChipsBeaverWidget.php'); | |
| 1226 | + flrt_include('src/Frontend/Builders/beaver/filters/FiltersBeaverWidget.php'); | |
| 1227 | + flrt_include('src/Frontend/Builders/beaver/sorting/SortingBeaverWidget.php'); | |
| 1228 | + } | |
| 1229 | +} | |
| 1230 | +add_action( 'init', 'wpc_beaver_builder_widgets_load' ); | |
| 1231 | + | |
| 1232 | +/** | |
| 1233 | + * XStore theme — "Display variable products as single variations" compatibility. | |
| 1234 | + * | |
| 1235 | + * With that XStore option (variable_products_detach) the theme: | |
| 1236 | + * 1. adds 'product_variation' to the shop query's post_type, hides variable | |
| 1237 | + * parents via post__not_in and flags the query with single_variations_filter=yes; | |
| 1238 | + * 2. on posts_clauses (priority 20) appends a TOP-LEVEL | |
| 1239 | + * "OR ( post_type='product_variation' AND post_status='publish' AND … )" | |
| 1240 | + * branch, re-implementing WooCommerce's own layered-nav filters for the | |
| 1241 | + * detached variations (price, rating, brand, chosen attributes from $_GET). | |
| 1242 | + * | |
| 1243 | + * The theme knows nothing about Filter Everything, so on FE-filtered pages that | |
| 1244 | + * OR branch let EVERY published variation into the results, past FE's term | |
| 1245 | + * constraints — filtering visually "did nothing" (each alternative of a | |
| 1246 | + * top-level OR must repeat the filter conditions). | |
| 1247 | + * | |
| 1248 | + * Fix: append FE's active filter constraints AFTER the theme's branch | |
| 1249 | + * (priority 30). AND binds tighter than OR, so in | |
| 1250 | + * <first alternative> OR ( <theme branch> ) AND ( <FE constraints> ) | |
| 1251 | + * the constraints apply to the variations branch only, leaving the first | |
| 1252 | + * alternative (already filtered by FE the regular way) untouched. | |
| 1253 | + */ | |
| 1254 | +function flrt_xstore_detached_variations_where( $clauses, $wp_query ) { | |
| 1255 | + global $wpdb; | |
| 1256 | + | |
| 1257 | + if ( is_admin() || empty( $clauses['where'] ) ) { | |
| 1258 | + return $clauses; | |
| 1259 | + } | |
| 1260 | + | |
| 1261 | + // Only XStore "detached variations" queries that FE has actually filtered. | |
| 1262 | + if ( $wp_query->get( 'single_variations_filter' ) !== 'yes' || ! $wp_query->get( 'flrt_filtered_query' ) ) { | |
| 1263 | + return $clauses; | |
| 1264 | + } | |
| 1265 | + | |
| 1266 | + // The theme adds its branch at priority 20 — bail if it is not there. | |
| 1267 | + if ( strpos( $clauses['where'], "OR ({$wpdb->posts}.post_type = 'product_variation'" ) === false ) { | |
| 1268 | + return $clauses; | |
| 1269 | + } | |
| 1270 | + | |
| 1271 | + $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager(); | |
| 1272 | + $queried_values = $wpManager->getQueryVar( 'queried_values' ); | |
| 1273 | + | |
| 1274 | + if ( empty( $queried_values ) || ! is_array( $queried_values ) ) { | |
| 1275 | + return $clauses; | |
| 1276 | + } | |
| 1277 | + | |
| 1278 | + $conditions = []; | |
| 1279 | + | |
| 1280 | + foreach ( $queried_values as $queried ) { | |
| 1281 | + | |
| 1282 | + if ( ! isset( $queried['entity'], $queried['e_name'] ) ) { | |
| 1283 | + continue; | |
| 1284 | + } | |
| 1285 | + | |
| 1286 | + // Taxonomy filters: a variation matches when its PARENT product carries | |
| 1287 | + // the term (variations have no term_relationships rows of their own). | |
| 1288 | + if ( $queried['entity'] === 'taxonomy' && ! empty( $queried['values'] ) ) { | |
| 1289 | + $tax = $queried['e_name']; | |
| 1290 | + $and_logic = ( isset( $queried['logic'] ) && $queried['logic'] === 'and' ); | |
| 1291 | + $groups = []; // one ttid-group per condition: single for OR-logic, per-term for AND-logic | |
| 1292 | + $slugs = []; | |
| 1293 | + | |
| 1294 | + foreach ( (array) $queried['values'] as $value_slug ) { | |
| 1295 | + $term = get_term_by( 'slug', $value_slug, $tax ); | |
| 1296 | + if ( ! $term ) { | |
| 1297 | + continue; | |
| 1298 | + } | |
| 1299 | + $slugs[] = esc_sql( $term->slug ); | |
| 1300 | + | |
| 1301 | + $ttids = [ (int) $term->term_taxonomy_id ]; | |
| 1302 | + if ( is_taxonomy_hierarchical( $tax ) && ! $and_logic ) { | |
| 1303 | + foreach ( get_term_children( $term->term_id, $tax ) as $child_id ) { | |
| 1304 | + $child = get_term( $child_id, $tax ); | |
| 1305 | + if ( $child && ! is_wp_error( $child ) ) { | |
| 1306 | + $ttids[] = (int) $child->term_taxonomy_id; | |
| 1307 | + } | |
| 1308 | + } | |
| 1309 | + } | |
| 1310 | + | |
| 1311 | + if ( $and_logic ) { | |
| 1312 | + $groups[] = $ttids; // every term required — own condition each | |
| 1313 | + } elseif ( empty( $groups ) ) { | |
| 1314 | + $groups[] = $ttids; // any term enough — collect into one IN() | |
| 1315 | + } else { | |
| 1316 | + $groups[0] = array_merge( $groups[0], $ttids ); | |
| 1317 | + } | |
| 1318 | + } | |
| 1319 | + | |
| 1320 | + if ( empty( $groups ) ) { | |
| 1321 | + continue; | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + foreach ( $groups as $group_ttids ) { | |
| 1325 | + $ttids_in = implode( ',', array_unique( $group_ttids ) ); | |
| 1326 | + $parent_has_term = "{$wpdb->posts}.post_parent IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ({$ttids_in}) )"; | |
| 1327 | + | |
| 1328 | + if ( strpos( $tax, 'pa_' ) === 0 && ! $and_logic && ! empty( $slugs ) ) { | |
| 1329 | + // Variation attributes: prefer the variation's own value — | |
| 1330 | + // a variation with a DIFFERENT value must not ride in on its | |
| 1331 | + // parent's term. Variations without own value ("Any …") | |
| 1332 | + // fall back to the parent's term. | |
| 1333 | + $meta_key = esc_sql( 'attribute_' . $tax ); | |
| 1334 | + $slugs_in = "'" . implode( "','", $slugs ) . "'"; | |
| 1335 | + | |
| 1336 | + $conditions[] = "( {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value IN ({$slugs_in}) )" | |
| 1337 | + . " OR ( {$parent_has_term}" | |
| 1338 | + . " AND {$wpdb->posts}.ID NOT IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value <> '' ) ) )"; | |
| 1339 | + } else { | |
| 1340 | + $conditions[] = $parent_has_term; | |
| 1341 | + } | |
| 1342 | + } | |
| 1343 | + } | |
| 1344 | + | |
| 1345 | + // Numeric meta filters (price and alike): variations carry their own value. | |
| 1346 | + if ( $queried['entity'] === 'post_meta_num' && isset( $queried['values'] ) && is_array( $queried['values'] ) ) { | |
| 1347 | + $meta_key = esc_sql( $queried['e_name'] ); | |
| 1348 | + $min = ( isset( $queried['values']['min'] ) && $queried['values']['min'] !== '' ) ? (float) $queried['values']['min'] : false; | |
| 1349 | + $max = ( isset( $queried['values']['max'] ) && $queried['values']['max'] !== '' ) ? (float) $queried['values']['max'] : false; | |
| 1350 | + | |
| 1351 | + $range = []; | |
| 1352 | + if ( $min !== false ) { | |
| 1353 | + $range[] = "CAST(meta_value AS DECIMAL(15,6)) >= {$min}"; | |
| 1354 | + } | |
| 1355 | + if ( $max !== false ) { | |
| 1356 | + $range[] = "CAST(meta_value AS DECIMAL(15,6)) <= {$max}"; | |
| 1357 | + } | |
| 1358 | + | |
| 1359 | + if ( $range ) { | |
| 1360 | + $conditions[] = "{$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND " . implode( ' AND ', $range ) . " )"; | |
| 1361 | + } | |
| 1362 | + } | |
| 1363 | + | |
| 1364 | + // Other filter entities (post_meta choices, author, post_date …) are not | |
| 1365 | + // mirrored into the variations branch yet — they are rare on shop archives. | |
| 1366 | + } | |
| 1367 | + | |
| 1368 | + if ( ! empty( $conditions ) ) { | |
| 1369 | + $clauses['where'] .= ' AND ( ' . implode( ' ) AND ( ', $conditions ) . ' )'; | |
| 1370 | + } | |
| 1371 | + | |
| 1372 | + return $clauses; | |
| 1373 | +} | |
| 1374 | +add_filter( 'posts_clauses', 'flrt_xstore_detached_variations_where', 30, 2 ); | |
| 1375 | + | |
| 1376 | +//@todo check this with PLL support | |
| 1377 | +//function flrt_add_cpt_to_pll_tmp( $post_types, $is_settings ) { | |
| 1378 | +// if ( $is_settings ) { | |
| 1379 | +// $post_types[ FLRT_FILTERS_SET_POST_TYPE ] = FLRT_FILTERS_SET_POST_TYPE; | |
| 1380 | +// } | |
| 1381 | +// return $post_types; | |
| 1382 | +//} | |