PluginProbe
Filter Everything — WordPress & WooCommerce Filters / 1.9.7
Filter Everything — WordPress & WooCommerce Filters v1.9.7
1.9.7 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 All 52 releases
← All changes | src/wpc-default-hooks.php +184 -26 1.9.2.11.9.7 View file →
@@ -30,8 +30,12 @@
30 30 add_action('wpc_after_filter_input', 'flrt_after_filter_input');
31 31 add_filter('wpc_filters_checkbox_term_html', 'wpc_term_brand_logo', 5, 4);
32 32 add_filter('wpc_filters_radio_term_html', 'wpc_term_brand_logo', 5, 4);
33 33 add_filter('wpc_filters_label_term_html', 'wpc_term_brand_logo', 5, 4);
34 + add_filter('wpc_filters_checkbox_term_html', 'wpc_replace_links_with_spans', 11, 4);
35 + add_filter('wpc_filters_radio_term_html', 'wpc_replace_links_with_spans', 11, 4);
36 + add_filter('wpc_filters_label_term_html', 'wpc_replace_links_with_spans', 11, 4);
37 + add_filter('wpc_filters_rating_term_html', 'wpc_replace_links_with_spans', 11, 4);
34 38 add_filter('wpc_taxonomy_location_terms', 'flrt_remove_default_category_location', 10, 2);
35 39 add_filter( 'wpc_set_num_shift', 'flrt_round_numeric_values', 10, 3 );
36 40
37 41 if (!function_exists('flrt_ucfirst_term_slug_name')) {
@@ -180,9 +184,8 @@
180 184 {
181 185 if (isset($attributes['class']) && $attributes['class'] === 'wpc-field-slug' && $attributes['value'] === '') {
182 186 echo '<p class="description">' . esc_html__('a-z, 0-9, "_" and "-" symbols supported only', 'filter-everything') . '</p>';
183 187 }
184 -
185 188 }
186 189 }
187 190
188 191 if (!function_exists('wpc_term_brand_logo')) {
@@ -195,13 +198,13 @@
195 198 return $html;
196 199 }
197 200 $src = flrt_get_term_brand_image($term->term_id, $filter);
198 201
199 - $link_attributes .= ' title="' . $term->name . '"';
202 + $link_attributes .= ' title="' . esc_attr( $term->name ) . '"';
200 203
201 204 if ($src) {
202 - $img = '<span class="wpc-term-image-wrapper"><img src="' . $src . '" alt="' . $term->name . '" /></span>';
203 - $html = '<a ' . $link_attributes . '>' . $img . '<span class="wpc-term-name">' . $term->name . '</span></a>';
205 + $img = '<span class="wpc-term-image-wrapper"><img src="' . esc_url( $src ) . '" alt="' . esc_attr( $term->name ) . '" /></span>';
206 + $html = '<a ' . $link_attributes . '>' . $img . '<span class="wpc-term-name">' . esc_html( $term->name ) . '</span></a>';
204 207 }
205 208
206 209 return $html;
207 210 }
@@ -208,8 +211,14 @@
208 211 }
209 212
210 213 if( !function_exists( 'flrt_remove_default_category_location' ) ) {
211 214 function flrt_remove_default_category_location( $terms, $taxonomy ){
215 + // Bail on anything that is not a terms array (e.g. WP_Error when the
216 + // taxonomy is unavailable) so we never index into a non-array.
217 + if ( is_wp_error( $terms ) || ! is_array( $terms ) ) {
218 + return $terms;
219 + }
220 +
212 221 $default_category = 0;
213 222
214 223 if ( $taxonomy === 'product_cat' ) {
215 224 $default_category = get_option( 'default_product_cat' );
@@ -266,11 +275,13 @@
266 275 return $value;
267 276 }
268 277
269 278 }
279 +
270 280 function flrt_chips( $showReset = false, $setIds = [] ) {
271 281 $templateManager = \FilterEverything\Filter\Container::instance()->getTemplateManager();
272 282 $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
283 + $filterSet = Container::instance()->getFilterSetService();
273 284
274 285 if( empty( $setIds ) || ! $setIds || ! is_array( $setIds ) ){
275 286 $relatedSetIds = $wpManager->getQueryVar('wpc_page_related_set_ids');
276 287
@@ -424,25 +435,8 @@
424 435
425 436 return $classes;
426 437 }
427 438
428 -//add_filter( 'wpc_filter_classes', 'flrt_same_swatches_width', 20, 4 );
429 -//function flrt_same_swatches_width( $classes, $filter, $default_classes, $terms, $args ){
430 -// if( in_array( 'wpc-filter-has-swatches', $classes ) ){
431 -// if( ! empty( $terms ) ) {
432 -// $counters = [];
433 -// foreach ( $terms as $single_term ) {
434 -// $counters[] = $single_term->cross_count;
435 -// }
436 -//
437 -// $max = max( $counters );
438 -// $classes[] = 'wpc-counter-width-'. strlen( (string)$max );
439 -// }
440 -// }
441 -// return $classes;
442 -//}
443 -
444 -
445 439 // Bricks Builder fix for Any Category Filter Set
446 440 add_action( 'wpc_all_set_wp_queried_posts', 'flrt_bricks_builder_category_compat', 10, 2 );
447 441 function flrt_bricks_builder_category_compat( $set_wp_query, $setId ){
448 442
@@ -473,12 +467,13 @@
473 467 // 'max_num_label'
474 468
475 469 if( $filter['min_num_label'] !== '' ){
476 470 if( ! is_null( $term ) && property_exists( $term, 'slug' ) && in_array( $term->slug, ['min', 'from'] ) ){
471 + $value = flrt_chips_label_value( $filter, $term->slug );
477 472 if( strpos( $filter['min_num_label'], '{value}' ) !== false ){
478 - $term_name = str_replace( '{value}', $filter['values'][$term->slug], $filter['min_num_label'] );
473 + $term_name = str_replace( '{value}', $value, $filter['min_num_label'] );
479 474 }else {
480 - $term_name = $filter['min_num_label'] .' '.$filter['values'][$term->slug];
475 + $term_name = $filter['min_num_label'] .' '.$value;
481 476 }
482 477
483 478 }
484 479 }
@@ -484,12 +479,13 @@
484 479 }
485 480
486 481 if( $filter['max_num_label'] !== '' ){
487 482 if( ! is_null( $term ) && property_exists( $term, 'slug' ) && in_array( $term->slug, ['max', 'to'] ) ){
483 + $value = flrt_chips_label_value( $filter, $term->slug );
488 484 if( strpos( $filter['max_num_label'], '{value}' ) !== false ){
489 - $term_name = str_replace( '{value}', $filter['values'][$term->slug], $filter['max_num_label'] );
485 + $term_name = str_replace( '{value}', $value, $filter['max_num_label'] );
490 486 }else {
491 - $term_name = $filter['max_num_label'] .' '.$filter['values'][$term->slug];
487 + $term_name = $filter['max_num_label'] .' '.$value;
492 488 }
493 489 }
494 490 }
495 491
@@ -497,8 +493,38 @@
497 493
498 494 return $term_name;
499 495 }
500 496
497 +/**
498 + * Queried value for a {value} chip label. Date values must respect the
499 + * filter's Date Format option, like the default term names built in
500 + * PostDateEntity::createTermName() do (raw URL values otherwise leak
501 + * into the chips).
502 + */
503 +function flrt_chips_label_value( $filter, $edge ) {
504 + $value = isset( $filter['values'][ $edge ] ) ? $filter['values'][ $edge ] : '';
505 +
506 + if ( in_array( $filter['entity'], [ 'post_date', 'post_meta_date' ] ) && ! empty( $filter['date_format'] ) ) {
507 + $format = $filter['date_format'];
508 + $date_type = flrt_detect_date_type( $value );
509 +
510 + // In case if we have several date filters on the same page
511 + if ( in_array( $date_type, [ 'date', 'time' ] ) ) {
512 + $maybe_split_format = flrt_split_date_time( $format );
513 + if ( isset( $maybe_split_format[ $date_type ] ) ) {
514 + $format = $maybe_split_format[ $date_type ];
515 + }
516 + }
517 +
518 + $formatted = flrt_apply_date_format( $value, $format );
519 + if ( $formatted ) {
520 + $value = $formatted;
521 + }
522 + }
523 +
524 + return $value;
525 +}
526 +
501 527 add_filter( 'query_loop_block_query_vars', 'flrt_query_loop_block_query_vars', 10, 2 );
502 528
503 529 function flrt_query_loop_block_query_vars( $query, $block ){
504 530 global $xd;
@@ -762,9 +788,9 @@
762 788 $include_custom_meta_keys,
763 789 static fn(string $key) => strncmp($key, $q, strlen($q)) === 0
764 790 ));
765 791 }
766 - $default_items = array_map(static function ($k) {
792 + $default_items = array_map(static function ($k) use ($include_custom_meta_keys) {
767 793 return [
768 794 'id' => $k,
769 795 'text' => $include_custom_meta_keys[$k],
770 796 ];
@@ -850,8 +876,140 @@
850 876 });
851 877 }
852 878
853 879
880 +/**
881 + * PRO-only fields have no inputs in the free admin UI, so saving in the free
882 + * version would silently wipe their values from the DB. Instead, carry the
883 + * previously saved values over — they must survive free-mode saves and start
884 + * working again after switching back to PRO. In the free version their
885 + * runtime effect is disabled at read time (see the hooks below), not in the DB.
886 + */
887 +add_filter('wpc_pre_save_filter', function($filter) {
888 + if( !defined('FLRT_FILTERS_PRO')) {
889 + $proFields = array('show_range_list', 'range_list_input', 'used_for_variations');
890 +
891 + // Values for these fields can not come from the free UI — drop any posted ones
892 + foreach ($proFields as $proField) {
893 + unset($filter[$proField]);
894 + }
895 +
896 + if (!empty($filter['ID']) && is_numeric($filter['ID'])) {
897 + $savedPost = get_post((int) $filter['ID']);
898 +
899 + if ($savedPost && $savedPost->post_type === FLRT_FILTERS_POST_TYPE) {
900 + $savedFields = (array) maybe_unserialize($savedPost->post_content);
901 +
902 + foreach ($proFields as $proField) {
903 + if (isset($savedFields[$proField])) {
904 + $filter[$proField] = $savedFields[$proField];
905 + }
906 + }
907 + }
908 + }
909 + }
910 + return $filter;
911 +});
912 +
913 +add_filter('wpc_pre_save_set_fields', function($setFields) {
914 + if( !defined('FLRT_FILTERS_PRO')) {
915 + $proFields = array('hide_empty_filter', 'custom_posts_container', 'apply_button_page_type', 'apply_button_post_name');
916 +
917 + foreach ($proFields as $proField) {
918 + unset($setFields[$proField]);
919 + }
920 +
921 + if (!empty($setFields['ID']) && is_numeric($setFields['ID'])) {
922 + $savedPost = get_post((int) $setFields['ID']);
923 +
924 + if ($savedPost && $savedPost->post_type === FLRT_FILTERS_SET_POST_TYPE) {
925 + $savedFields = (array) maybe_unserialize($savedPost->post_content);
926 +
927 + foreach ($proFields as $proField) {
928 + if (isset($savedFields[$proField])) {
929 + $setFields[$proField] = $savedFields[$proField];
930 + }
931 + }
932 + }
933 + }
934 + }
935 + return $setFields;
936 +});
937 +
938 +/**
939 + * PRO-only plugin settings have no inputs in the free Settings UI (they render
940 + * as "Unlock with PRO"), so saving the settings form in the free version would
941 + * silently drop their values from the option. Carry the previously saved
942 + * values over — they must survive free-mode saves and start working again
943 + * after switching back to PRO. Their runtime effect is disabled at read time
944 + * (flrt_instant_recount). Since 1.9.6 «Disable filter links for crawlers» is a
945 + * regular option in both builds and no longer belongs here.
946 + */
947 +add_filter('pre_update_option_wpc_filter_settings', function($value, $old_value) {
948 + if( !defined('FLRT_FILTERS_PRO')) {
949 + $proOptions = array('apply_button_instant_recount');
950 +
951 + foreach ($proOptions as $proOption) {
952 + // Values for these keys can not come from the free UI — drop any posted ones
953 + if (is_array($value)) {
954 + unset($value[$proOption]);
955 + }
956 +
957 + if (is_array($old_value) && isset($old_value[$proOption])) {
958 + if (!is_array($value)) {
959 + $value = array();
960 + }
961 + $value[$proOption] = $old_value[$proOption];
962 + }
963 + }
964 + }
965 + return $value;
966 +}, 10, 2);
967 +
968 +/**
969 + * Runtime gate for the free version: the PRO-only values preserved in the DB
970 + * must not activate PRO features while the plugin runs as free.
971 + */
972 +add_filter('wpc_after_get_filter', function($filter) {
973 + if( !defined('FLRT_FILTERS_PRO')) {
974 + $filter['show_range_list'] = '';
975 + $filter['range_list_input'] = ''; // '' matches getEmptyFilter() and disables the JS range-list branch
976 + $filter['used_for_variations'] = '';
977 + }
978 + return $filter;
979 +});
980 +
981 +add_filter('wpc_filter_before_make_default_set_values', function($parsed) {
982 + if( !defined('FLRT_FILTERS_PRO')) {
983 + foreach (array('hide_empty_filter', 'custom_posts_container', 'apply_button_page_type', 'apply_button_post_name') as $proField) {
984 + unset($parsed[$proField]);
985 + }
986 + }
987 + return $parsed;
988 +});
989 +
990 +if (!function_exists('wpc_replace_links_with_spans')) {
991 + function wpc_replace_links_with_spans($term_name, $attributes = '', $term = false, $filter = false)
992 + {
993 + // Available in both builds since 1.9.6: in free every filter link becomes
994 + // a <span> (filter pages are noindex there by design); PRO keeps a real
995 + // <a> for the targets its SEO Rules index (smart spans)
996 + if( flrt_get_option('disable_filter_links_for_bots') === 'on' ) {
997 + // Keep a real <a> when the target page is indexable (within the
998 + // Indexing Depth) — hiding pages the SEO layer indexes would
999 + // starve them of internal links; only the noise stays hidden (PRO;
1000 + // the helper does not exist in free, so nothing is exempt there)
1001 + if ( $term && $filter && function_exists('flrt_indexable_link_target')
1002 + && flrt_indexable_link_target( $term, $filter ) ) {
1003 + return $term_name;
1004 + }
1005 + $term_name = str_replace('<a', '<span', $term_name);
1006 + $term_name = str_replace('href', 'data-wpc-span-link', $term_name);
1007 + return str_replace('</a>', '</span>', $term_name);
1008 + }
1009 + return $term_name;
1010 + }
1011 +}
854 1012
855 1013 //add_filter( 'stackable/posts/post_query', 'flrt_stackable_block_query_vars', 10, 3 );
856 1014 //function flrt_stackable_block_query_vars( $post_query, $context, $query_string ){
857 1015 // if( is_user_logged_in() ) {