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-default-hooks.php

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

1,021 lines 38.6 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 use FilterEverything\Filter\Container;
8 use \FilterEverything\Filter\PostDateEntity;
9 use \FilterEverything\Filter\ImportSettings;
10
11 // Make post type name lowercase in posts found message
12 add_filter( 'wpc_label_singular_posts_found_msg', 'mb_strtolower' );
13 add_filter( 'wpc_label_plural_posts_found_msg', 'mb_strtolower' );
14
15 add_action( 'init', 'flrt_initiate_overridden_functions' );
16 function flrt_initiate_overridden_functions()
17 {
18 // All hooks with function wrapper with function_exists()
19 add_filter('wpc_filter_post_meta_num_term_name', 'flrt_ucfirst_term_slug_name');
20 add_filter('wpc_filter_post_meta_term_name', 'flrt_ucfirst_term_slug_name');
21 add_filter('wpc_filter_tax_numeric_term_name', 'flrt_ucfirst_term_slug_name');
22 add_filter('wpc_filter_post_meta_exists_term_name', 'flrt_custom_field_exists_name');
23 add_filter('wpc_filter_post_meta_term_name', 'flrt_stock_status_term_name', 10, 2);
24 add_filter('wpc_filter_post_meta_exists_term_name', 'flrt_on_sale_term_name', 15, 2);
25 add_filter('wpc_filter_taxonomy_term_name', 'flrt_modify_taxonomy_term_name', 10, 2);
26 add_filter('wpc_filter_term_query_args', 'flrt_exclude_uncategorized_category', 10, 3);
27 add_filter('wpc_filter_get_taxonomy_terms', 'flrt_exclude_product_visibility_terms', 10, 2);
28 add_filter('wpc_filter_author_query_post_types', 'flrt_remove_author_query_post_types');
29 add_filter('wpc_filter_post_types', 'flrt_exclude_post_types');
30 add_action('wpc_after_filter_input', 'flrt_after_filter_input');
31 add_filter('wpc_filters_checkbox_term_html', 'wpc_term_brand_logo', 5, 4);
32 add_filter('wpc_filters_radio_term_html', 'wpc_term_brand_logo', 5, 4);
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);
38 add_filter('wpc_taxonomy_location_terms', 'flrt_remove_default_category_location', 10, 2);
39 add_filter( 'wpc_set_num_shift', 'flrt_round_numeric_values', 10, 3 );
40
41 if (!function_exists('flrt_ucfirst_term_slug_name')) {
42 function flrt_ucfirst_term_slug_name($term_name)
43 {
44 $term_name = flrt_ucfirst($term_name);
45 return $term_name;
46 }
47 }
48
49
50 if (!function_exists('flrt_custom_field_exists_name')) {
51 function flrt_custom_field_exists_name($term_name)
52 {
53 if ($term_name === 'yes') {
54 return esc_html__('Yes', 'filter-everything');
55 } else if ($term_name === 'no') {
56 return esc_html__('No', 'filter-everything');
57 }
58 return $term_name;
59 }
60 }
61
62 if (!function_exists('flrt_stock_status_term_name')) {
63 function flrt_stock_status_term_name($term_name, $e_name)
64 {
65 if ($e_name === '_stock_status') {
66 $term_name = strtolower($term_name);
67 if ($term_name === "instock") {
68 $term_name = esc_html__('In stock', 'filter-everything');
69 }
70
71 if ($term_name === "onbackorder") {
72 $term_name = esc_html__('On backorder', 'filter-everything');
73 }
74
75 if ($term_name === "outofstock") {
76 $term_name = esc_html__('Out of stock', 'filter-everything');
77 }
78 }
79
80 return $term_name;
81 }
82 }
83
84 if (!function_exists('flrt_on_sale_term_name')) {
85 function flrt_on_sale_term_name($term_name, $entity)
86 {
87 if ($entity === '_sale_price') {
88 $check_name = mb_strtolower($term_name);
89
90 if (in_array($check_name, ['yes', 'ja', 'ano', '', 'так'])) {
91 $term_name = esc_html__('On Sale', 'filter-everything');
92 }
93 if (in_array($check_name, ['no', 'nein', 'ne', 'ні'])) {
94 $term_name = esc_html__('Regular price', 'filter-everything');
95 }
96 }
97 return $term_name;
98 }
99 }
100
101
102 if (!function_exists('flrt_modify_taxonomy_term_name')) {
103 function flrt_modify_taxonomy_term_name($term_name, $e_name)
104 {
105 if (in_array($e_name, array('product_type', 'product_visibility'))) {
106 $term_name = flrt_ucfirst($term_name);
107 }
108 return $term_name;
109 }
110 }
111
112
113 if (!function_exists('flrt_exclude_uncategorized_category')) {
114 function flrt_exclude_uncategorized_category($args, $entity, $e_name)
115 {
116 if ($e_name === 'category') {
117 $args['exclude'] = array(1); // Uncategorized category
118 }
119
120 return $args;
121 }
122 }
123
124
125 if (!function_exists('flrt_exclude_product_visibility_terms')) {
126 function flrt_exclude_product_visibility_terms($terms, $e_name)
127 {
128 if ($e_name === 'product_visibility') {
129 if (is_array($terms)) {
130 foreach ($terms as $index => $term) {
131
132 if (in_array($term->slug, array('exclude-from-search', 'exclude-from-catalog'))) {
133 unset($terms[$index]);
134 }
135 }
136 }
137 }
138
139 if ($e_name === 'product_cat') {
140 if (is_array($terms)) {
141 foreach ($terms as $index => $term) {
142 if (in_array($term->slug, array('uncategorized'))) {
143 unset($terms[$index]);
144 }
145 }
146 }
147 }
148
149 return $terms;
150 }
151 }
152
153 if (!function_exists('flrt_remove_author_query_post_types')) {
154 function flrt_remove_author_query_post_types($post_types)
155 {
156 if (isset($post_types['attachment'])) {
157 unset($post_types['attachment']);
158 }
159 return $post_types;
160 }
161 }
162
163 if (!function_exists('flrt_exclude_post_types')) {
164 function flrt_exclude_post_types($post_types)
165 {
166
167 $post_types = array(
168 FLRT_FILTERS_POST_TYPE,
169 FLRT_FILTERS_SET_POST_TYPE,
170 'attachment',
171 'elementor_library',
172 'e-landing-page',
173 'jet-smart-filters',
174 'ct_template'
175 );
176
177 return $post_types;
178 }
179 }
180
181
182 if (!function_exists('flrt_after_filter_input')) {
183 function flrt_after_filter_input($attributes)
184 {
185 if (isset($attributes['class']) && $attributes['class'] === 'wpc-field-slug' && $attributes['value'] === '') {
186 echo '<p class="description">' . esc_html__('a-z, 0-9, "_" and "-" symbols supported only', 'filter-everything') . '</p>';
187 }
188 }
189 }
190
191 if (!function_exists('wpc_term_brand_logo')) {
192 function wpc_term_brand_logo($html, $link_attributes, $term, $filter)
193 {
194 if (!in_array($filter['e_name'], flrt_brand_filter_entities())) {
195 return $html;
196 }
197 if (!isset($term->slug)) {
198 return $html;
199 }
200 $src = flrt_get_term_brand_image($term->term_id, $filter);
201
202 $link_attributes .= ' title="' . esc_attr( $term->name ) . '"';
203
204 if ($src) {
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>';
207 }
208
209 return $html;
210 }
211 }
212
213 if( !function_exists( 'flrt_remove_default_category_location' ) ) {
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
221 $default_category = 0;
222
223 if ( $taxonomy === 'product_cat' ) {
224 $default_category = get_option( 'default_product_cat' );
225 } elseif( $taxonomy === 'category' ) {
226 $default_category = get_option('default_category');
227 }
228
229 // Remove default category from the list
230 if ( $default_category > 0 ) {
231 unset( $terms[ $default_category ] );
232 }
233
234 return $terms;
235 }
236 }
237
238 /**
239 * Fix for the LiveCanvas page builder
240 */
241 if( defined( 'LC_MU_PLUGIN_NAME' ) && LC_MU_PLUGIN_NAME === 'livecanvas-must-use-plugin.php' ) {
242 add_filter('wpc_pre_save_set_fields', 'flrt_safe_save_set_fields');
243 function flrt_safe_save_set_fields($setFields)
244 {
245
246 if (isset($setFields['wp_filter_query_vars'])) {
247 $query_vars = $setFields['wp_filter_query_vars'];
248 $new_query_vars = [];
249 $search_values = [
250 ''
251 ];
252 $replace_values = [
253 '&hellip;'
254 ];
255
256 foreach ($query_vars as $hash => $vars_serialized_str) {
257 $new_query_vars[$hash] = str_replace($search_values, $replace_values, $vars_serialized_str);
258 }
259
260 $setFields['wp_filter_query_vars'] = $new_query_vars;
261 }
262
263 return $setFields;
264 }
265 }
266
267 function flrt_round_numeric_values( $value, $entity_name, $limit )
268 {
269 if( $limit === 'min' ) {
270 $value = floor( $value );
271 } elseif ( $limit === 'max' ){
272 $value = ceil( $value );
273 }
274
275 return $value;
276 }
277
278 }
279
280 function flrt_chips( $showReset = false, $setIds = [] ) {
281 $templateManager = \FilterEverything\Filter\Container::instance()->getTemplateManager();
282 $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
283 $filterSet = Container::instance()->getFilterSetService();
284
285 if( empty( $setIds ) || ! $setIds || ! is_array( $setIds ) ){
286 $relatedSetIds = $wpManager->getQueryVar('wpc_page_related_set_ids');
287
288 if( is_array( $relatedSetIds ) ) {
289 foreach ( $relatedSetIds as $set ){
290 $setIds[] = $set['ID'];
291 }
292 }
293 }
294
295 $chipsObj = new \FilterEverything\Filter\Chips( $showReset, $setIds );
296 $chips = $chipsObj->getChips();
297
298 $templateManager->includeFrontView( 'chips', array( 'chips' => $chips, 'setid' => reset($setIds) ) );
299 }
300
301 function flrt_show_selected_terms( $showReset = true, $setIds = [], $class = [] )
302 {
303 $default_class = array('wpc-custom-selected-terms');
304
305 if(! empty( $class ) && is_array($class) ){
306 $default_class = array_merge( $default_class, $class );
307 }
308
309 if( isset( $_POST['action'] ) && $_POST['action'] === 'elementor_ajax' ){
310 echo '<strong>'.esc_html__( 'Filter Everything &mdash; Chips', 'filter-everything' ).'</strong>';
311 return;
312 }
313
314 if( isset( $_GET['action'] ) && $_GET['action'] === 'elementor' ){
315 echo '<strong>'.esc_html__( 'Filter Everything &mdash; Chips', 'filter-everything' ).'</strong>';
316 return;
317 }
318
319 echo '<div class="'.implode(' ', $default_class).'">'."\r\n";
320 flrt_chips( $showReset, $setIds );
321 echo '</div>'."\r\n";
322 }
323
324 add_filter( 'wpc_dropdown_option_attr', 'flrt_parse_dropdown_value' );
325 function flrt_parse_dropdown_value( $attr ){
326 if( ! is_array( $attr ) ){
327 $new_attr = array();
328 $new_attr['label'] = $attr;
329 return $new_attr;
330 }
331
332 return $attr;
333 }
334
335 add_filter( 'wpc_unnecessary_get_parameters', 'flrt_unnecessary_get_parameters' );
336 function flrt_unnecessary_get_parameters( $params ){
337 $unnecessary_params = array(
338 'product-page' => true,
339 '_pjax' => true,
340 'cst' => true,
341 );
342
343 $get = \FilterEverything\Filter\Container::instance()->getTheGet();
344
345 if( ! empty( $get ) && is_array( $get ) ) {
346 foreach ( $get as $param_name => $param_value ) {
347 if( preg_match( '%query\-[0-9]+\-page%', $param_name ) ) {
348 $unnecessary_params[$param_name] = true;
349 }
350
351 if( preg_match( '%e\-page\-[a-zA-Z0-9]+%im', $param_name ) ) {
352 $unnecessary_params[$param_name] = true;
353 }
354 }
355 }
356
357 return array_merge( $params, $unnecessary_params );
358 }
359
360 add_filter('wpc_posts_containers', 'flrt_convert_posts_container_to_array');
361 function flrt_convert_posts_container_to_array( $container ){
362
363 if( ! is_array( $container ) ){
364 return [ 'default' => trim($container) ];
365 }
366
367 return $container;
368 }
369
370 add_filter( 'wpc_seo_title', 'do_shortcode' );
371 add_filter( 'wpc_seo_description', 'do_shortcode' );
372 add_filter( 'wpc_seo_h1', 'do_shortcode' );
373
374 /**
375 * @return int
376 * @since 1.7.1
377 */
378 function flrt_more_less_count() {
379 return apply_filters( 'wpc_more_less_count', 5 );
380 }
381 /**
382 * @return mixed|void
383 * @since 1.7.1
384 */
385 function flrt_more_less_opened() {
386 return apply_filters( 'wpc_more_less_opened', [] );
387 }
388 /**
389 * @return mixed|void
390 * @since 1.7.1
391 */
392 function flrt_folding_opened() {
393 return apply_filters( 'wpc_folding_opened', [] );
394 }
395 /**
396 * @return mixed|void
397 * @since 1.7.1
398 */
399 function flrt_hierarchy_opened() {
400 return apply_filters( 'wpc_hierarchy_opened', [] );
401 }
402 /**
403 * @param $filter
404 * @return mixed|void
405 * @since 1.7.1
406 */
407 function flrt_dropdown_default_option( $filter ) {
408 $label = sprintf( __( '- Select %s -', 'filter-everything' ), $filter['label'] );
409 if( isset( $filter['dropdown_label'] ) && $filter['dropdown_label'] ){
410 $label = $filter['dropdown_label'];
411 }
412 return apply_filters( 'wpc_dropdown_default_option', $label, $filter );
413 }
414
415 function flrt_brand_filter_entities(){
416 return apply_filters( 'wpc_brand_filter_entities', ['product_brand', 'pa_brand', 'pwb-brand', 'yith_product_brand'] );
417 }
418
419 add_filter( 'wpc_filter_classes', 'wpc_frontend_filter_classes', 10, 2 );
420 function wpc_frontend_filter_classes( $classes, $filter ){
421 if( in_array( $filter['e_name'], flrt_brand_filter_entities() ) ) {
422 $classes[] = 'wpc-filter-has-brands';
423 }
424
425 return $classes;
426 }
427
428 add_filter( 'wpc_filter_classes', 'flrt_frontend_filter_classes', 10, 2 );
429 function flrt_frontend_filter_classes( $classes, $filter ){
430 if ( $filter['show_term_names'] === 'yes' ) {
431 $classes[] = 'wpc-filter-visible-term-names';
432 } else {
433 $classes[] = 'wpc-filter-hidden-term-names';
434 }
435
436 return $classes;
437 }
438
439 // Bricks Builder fix for Any Category Filter Set
440 add_action( 'wpc_all_set_wp_queried_posts', 'flrt_bricks_builder_category_compat', 10, 2 );
441 function flrt_bricks_builder_category_compat( $set_wp_query, $setId ){
442
443 //to check if there is Bricks Builder
444 if ( defined( 'BRICKS_VERSION' ) && BRICKS_VERSION ) {
445 $filterSet = \FilterEverything\Filter\Container::instance()->getFilterSetService();
446 $the_set = $filterSet->getSet( $setId );
447
448 if ( isset( $the_set['wp_page_type']['value'] ) && isset( $the_set['post_name']['value'] ) ){
449 if ( strpos( $the_set['wp_page_type']['value'], 'taxonomy_' ) !== false ) {
450 if ( strpos( $the_set['post_name']['value'], '-1' ) !== false ) {
451 $queried_object = get_queried_object();
452 if ( property_exists( $queried_object, 'taxonomy' ) ){
453 $set_wp_query->set( $queried_object->taxonomy, $queried_object->slug );
454 }
455 }
456 }
457 }
458 }
459
460 return $set_wp_query;
461 }
462
463 add_filter( 'wpc_chips_term_name', 'flrt_chips_labels', 10, 3 );
464 function flrt_chips_labels( $term_name, $term, $filter ) {
465 if ( in_array( $filter['entity'], ['post_meta_num', 'tax_numeric', 'post_date', 'post_meta_date'] ) ) {
466 // 'min_num_label'
467 // 'max_num_label'
468
469 if( $filter['min_num_label'] !== '' ){
470 if( ! is_null( $term ) && property_exists( $term, 'slug' ) && in_array( $term->slug, ['min', 'from'] ) ){
471 $value = flrt_chips_label_value( $filter, $term->slug );
472 if( strpos( $filter['min_num_label'], '{value}' ) !== false ){
473 $term_name = str_replace( '{value}', $value, $filter['min_num_label'] );
474 }else {
475 $term_name = $filter['min_num_label'] .' '.$value;
476 }
477
478 }
479 }
480
481 if( $filter['max_num_label'] !== '' ){
482 if( ! is_null( $term ) && property_exists( $term, 'slug' ) && in_array( $term->slug, ['max', 'to'] ) ){
483 $value = flrt_chips_label_value( $filter, $term->slug );
484 if( strpos( $filter['max_num_label'], '{value}' ) !== false ){
485 $term_name = str_replace( '{value}', $value, $filter['max_num_label'] );
486 }else {
487 $term_name = $filter['max_num_label'] .' '.$value;
488 }
489 }
490 }
491
492 }
493
494 return $term_name;
495 }
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
527 add_filter( 'query_loop_block_query_vars', 'flrt_query_loop_block_query_vars', 10, 2 );
528
529 function flrt_query_loop_block_query_vars( $query, $block ){
530 global $xd;
531 $xd++;
532
533 if( ! is_null( $block ) && property_exists( $block, 'parsed_block' ) ){
534 if( isset( $block->parsed_block['blockName'] ) ) {
535 if( in_array( $block->parsed_block['blockName'],
536 [
537 'core/query-pagination-previous',
538 'core/query-pagination-next',
539 'core/query-pagination-numbers',
540 ]
541 ) ){
542 $query['flrt_pagination'] = true;
543 }
544 }
545 }
546
547 return $query;
548 }
549
550 add_filter( 'wpc_settings_field_checkbox', 'flrt_collapse_widget_checkbox_handler', 10, 2 );
551 function flrt_collapse_widget_checkbox_handler( $checkbox, $args )
552 {
553 $checkbox = '<div class="flrt-checkbox-switch-wrapper">';
554 $checkbox .= '<label class="flrt-checkbox-switch"><input type="checkbox" name="%s[%s]" %s id="%s" %s>';
555 $checkbox .= '<span class="flrt-checkbox-slider"></span>';
556 $checkbox .= '</label>';
557 $checkbox .= '<span class="wpc-checkbox-placeholder">%s</span>';
558 $checkbox .= '</div>';
559 return $checkbox;
560 }
561
562 add_filter( 'wpc_input_type_checkbox', 'flrt_input_checkbox_switcher', 10, 2 );
563 function flrt_input_checkbox_switcher( $html, $attributes )
564 {
565
566 $html_wrap = '<div class="flrt-checkbox-switch-wrapper">';
567 $html_wrap .= '<label class="flrt-checkbox-switch">';
568 $html_wrap .= $html;
569 $html_wrap .= '<span class="flrt-checkbox-slider"></span>';
570 $html_wrap .= '</label>';
571 $html_wrap .= '</div>';
572
573 return $html_wrap;
574 }
575
576
577 add_filter('wpc_get_broken_builders', function ($array) {
578 return [3669169978, 339203640];
579 }, 10, 1);
580
581
582
583 if(!defined('FLRT_FILTERS_PRO')) {
584
585 add_filter('flrt_before_render_admin_select_option', 'flrt_add_data_to_option_before_render', 10, 4);
586 function flrt_add_data_to_option_before_render($option_value, $attr, $label, $disabled)
587 {
588 $attributes = ' data-link="' . flrt_reneder_preview_link($option_value, $attr) . '"';
589
590 if(is_array($disabled) && in_array($option_value, $disabled)){
591 $class = $option_value . '-disabled';
592 $attributes .= ' class="' . $class . '"';
593 }
594
595 return $attributes;
596 }
597 function flrt_reneder_preview_link($option_value, $attr)
598 {
599 $link = '';
600 if ($attr['id'] == 'wpc_set_fields-post_type') {
601 if ($option_value == 'page') {
602 $option_value = 'post';
603 }
604
605
606
607 $archive_link = get_post_type_archive_link($option_value);
608 if ($archive_link) {
609 $link = $archive_link;
610 }
611
612 if (!$archive_link) {
613 $taxonomies = get_object_taxonomies($option_value);
614
615 if (!empty($taxonomies)) {
616 $first_taxonomy = $taxonomies[0];
617 $taxonomy = get_taxonomy($first_taxonomy);
618 if (!empty($taxonomy) && !is_wp_error($taxonomy)) {
619 $terms = get_terms([
620 'taxonomy' => $taxonomy->name,
621 'number' => 1,
622 'hide_empty' => false,
623 ]);
624 if (!empty($terms) && !is_wp_error($terms)) {
625 $term_link = get_term_link($terms[0]);
626 $link = esc_url($term_link);
627 }
628 }
629 }
630 }
631 }
632 return $link;
633 }
634 }
635
636 add_filter('wpc_is_check_errors_pro', function ($filter_sets, $query) {
637 $detector_class = 'FilterEverything\\Filter\\WP_Query_Source_Detector';
638 $is_allowed_method = 'is_allowed';
639 $source_var = 'flrt_detected_source';
640
641 if (defined('FLRT_FILTERS_PRO')) {
642 if (defined('FLRT_PRO_BUILDER_KEY')) {
643 $builder_key = apply_filters('wpc_builder_key_pro', $query->get($source_var), constant('FLRT_PRO_BUILDER_KEY'));
644
645 if ($detector_class::$is_allowed_method($builder_key)) {
646 return apply_filters('wpc_is_filtered_query_pro', [], $query);
647 }
648 }
649 }
650
651 if (!defined('FLRT_FILTERS_PRO')) {
652 $builder_key = apply_filters('wpc_builder_key', $query->get($source_var), $detector_class::$builder_key);
653
654 if ($detector_class::$is_allowed_method($builder_key)) {
655 return apply_filters('wpc_is_filtered_query_free', [], $query);
656 }
657 }
658
659 return [];
660 }, 10, 2);
661
662 add_filter('wpc_set_min_max', function($min_and_max, $filter_name) {
663 global $wp_query;
664
665 if (empty($wp_query->posts)) {
666 $min_and_max = ['min' => 0, 'max' => 0];
667 return $min_and_max;
668 }
669
670 return $min_and_max;
671 }, 10, 2);
672
673 if(!function_exists('wpc_default_custom_meta_keys_filter')){
674 function wpc_default_custom_meta_keys_filter(){
675 $normalize_keys = function($data) use (&$normalize_keys) {
676 $result = [];
677 foreach ($data as $k => $v) {
678 if (is_array($v)) {
679 $v = $normalize_keys($v);
680 }
681 if (is_int($k)) {
682 $result[(string)$v] = "";
683 } else {
684 $result[$k] = $v;
685 }
686 }
687 return $result;
688 };
689
690 $product_post_meta = array(
691 '_price' => esc_html__('filter by Product price', 'filter-everything'),
692 '_stock_status' => esc_html__('filter by Product stock status', 'filter-everything'),
693 '_sale_price' => esc_html__('filter by Product sale price', 'filter-everything'),
694 '_stock' => esc_html__('filter by Product stock quantity', 'filter-everything'),
695 'total_sales' => esc_html__('filter by Product total sales', 'filter-everything'),
696 '_backorders' => esc_html__('filter by Product backorders status', 'filter-everything'),
697 '_sold_individually' => esc_html__('filter by Product sold individually status', 'filter-everything'),
698 '_downloadable' => esc_html__('filter by Product downloadable status', 'filter-everything'),
699 '_virtual' => esc_html__('filter by Product virtual status', 'filter-everything'),
700 '_length' => esc_html__('filter by Product length', 'filter-everything'),
701 '_width' => esc_html__('filter by Product width', 'filter-everything'),
702 '_height' => esc_html__('filter by Product height', 'filter-everything'),
703 '_weight' => esc_html__('filter by Product weight', 'filter-everything'),
704 '_wc_average_rating' => esc_html__('filter by Product average rating', 'filter-everything'),
705 '_thumbnail_id' => esc_html__('filter by Featured image', 'filter-everything')
706 );
707 $product_post_meta_num = array(
708 '_price' => esc_html__('filter by Product price', 'filter-everything'),
709 '_stock' => esc_html__('filter by Product stock quantity', 'filter-everything'),
710 'total_sales' => esc_html__('filter by Product total sales', 'filter-everything'),
711 '_sale_price' => esc_html__('filter by Product sale price', 'filter-everything'),
712 '_stock_status' => esc_html__('filter by Product stock status', 'filter-everything'),
713 '_length' => esc_html__('filter by Product length', 'filter-everything'),
714 '_width' => esc_html__('filter by Product width', 'filter-everything'),
715 '_height' => esc_html__('filter by Product height', 'filter-everything'),
716 '_weight' => esc_html__('filter by Product weight', 'filter-everything'),
717 '_wc_average_rating' => esc_html__('filter by Product average rating', 'filter-everything'),
718 '_backorders' => esc_html__('filter by Product backorders status', 'filter-everything'),
719 '_sold_individually' => esc_html__('filter by Product sold individually status', 'filter-everything'),
720 '_downloadable' => esc_html__('filter by Product downloadable status', 'filter-everything'),
721 '_virtual' => esc_html__('filter by Product virtual status', 'filter-everything'),
722 '_thumbnail_id' => esc_html__('filter by Featured image', 'filter-everything'),
723 );
724 $product_post_meta_exists = array(
725 '_sale_price' => esc_html__('filter by Product on sale status', 'filter-everything'),
726 '_price' => esc_html__('filter by Product price', 'filter-everything'),
727 '_stock' => esc_html__('filter by Product stock quantity', 'filter-everything'),
728 'total_sales' => esc_html__('filter by Product total sales', 'filter-everything'),
729 '_stock_status' => esc_html__('filter by Product stock status', 'filter-everything'),
730 '_length' => esc_html__('filter by Product length', 'filter-everything'),
731 '_width' => esc_html__('filter by Product width', 'filter-everything'),
732 '_height' => esc_html__('filter by Product height', 'filter-everything'),
733 '_weight' => esc_html__('filter by Product weight', 'filter-everything'),
734 '_wc_average_rating' => esc_html__('filter by Product average rating', 'filter-everything'),
735 '_backorders' => esc_html__('filter by Product backorders status', 'filter-everything'),
736 '_sold_individually' => esc_html__('filter by Product sold individually status', 'filter-everything'),
737 '_downloadable' => esc_html__('filter by Product downloadable status', 'filter-everything'),
738 '_virtual' => esc_html__('filter by Product virtual status', 'filter-everything'),
739 '_thumbnail_id' => esc_html__('filter by Featured image', 'filter-everything'),
740 );
741 $all_post_types_post_meta_exists = array('_thumbnail_id' => esc_html__('filter by Featured image', 'filter-everything'));
742 $input = array(
743 'product' => array(
744 'post_meta' => $normalize_keys($product_post_meta),
745 'post_meta_num' => $normalize_keys($product_post_meta_num),
746 'post_meta_exists' => $normalize_keys($product_post_meta_exists)
747 ),
748 'all_post_types' => array(
749 'post_meta_exists' => $normalize_keys($all_post_types_post_meta_exists)
750 ),
751 );
752
753 return $normalize_keys($input);
754 }
755 }
756
757 add_action('wp_ajax_wpc_search_meta_keys', function () {
758 check_ajax_referer('wpc-f-set-nonce', '_flrt_nonce');
759
760 if ( ! current_user_can('edit_posts') ) {
761 wp_send_json_error(['message' => __('Forbidden', 'textdomain')], 403);
762 }
763
764 global $wpdb;
765
766 $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
767 $post_type = isset($_GET['post_type']) ? sanitize_key($_GET['post_type']) : 'post';
768 $post_meta_type = isset($_GET['post_meta_type']) ? sanitize_key($_GET['post_meta_type']) : '';
769
770 $include_custom_meta_keys = [];
771
772 if (!empty($post_type) && !empty($post_meta_type) && !empty(wpc_default_custom_meta_keys_filter()[$post_type][$post_meta_type])) {
773 foreach (wpc_default_custom_meta_keys_filter()[$post_type][$post_meta_type] as $key => $value) {
774 $include_custom_meta_keys[$key] = $value;
775 }
776 }
777
778 if (!empty($post_meta_type) && !empty(wpc_default_custom_meta_keys_filter()['all_post_types'][$post_meta_type])) {
779 foreach (wpc_default_custom_meta_keys_filter()['all_post_types'][$post_meta_type] as $key => $value) {
780 $include_custom_meta_keys[$key] = $value;
781 }
782 }
783
784 $default_custom_meta_keys = $include_custom_meta_keys;
785 $include_custom_meta_keys = array_values(array_unique(array_filter($include_custom_meta_keys)));
786 if(strlen($q) > 0){
787 $include_custom_meta_keys = array_values(array_filter(
788 $include_custom_meta_keys,
789 static fn(string $key) => strncmp($key, $q, strlen($q)) === 0
790 ));
791 }
792 $default_items = array_map(static function ($k) use ($include_custom_meta_keys) {
793 return [
794 'id' => $k,
795 'text' => $include_custom_meta_keys[$k],
796 ];
797 }, array_keys($include_custom_meta_keys) ?: []);
798
799 if (strlen($q) < 1) {
800 wp_send_json(['items' => $default_items]);
801 }
802
803 $like = '%' . $wpdb->esc_like($q) . '%';
804 $limit = 15;
805
806 $sql = $wpdb->prepare(
807 "SELECT DISTINCT pm.meta_key
808 FROM {$wpdb->postmeta} pm
809 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
810 WHERE p.post_type = %s
811 AND pm.meta_key LIKE %s ORDER BY pm.meta_key ASC
812 LIMIT %d",
813 $post_type,
814 $like,
815 $limit
816 );
817
818 $keys = $wpdb->get_col($sql);
819
820 $exact_match_index = array_search($q, $keys);
821 if ($exact_match_index !== false) {
822 unset($keys[$exact_match_index]);
823 array_unshift($keys, $q);
824 }
825 $items = array_map(static function ($k) use ($default_custom_meta_keys) {
826 $text = !empty($default_custom_meta_keys[$k]) ? $default_custom_meta_keys[$k] : '';
827 return [
828 'id' => $k,
829 'text' => $text,
830 ];
831 }, $keys ?: []);
832 if (strlen($q) > 1 && count($items) < 1) {
833 $items[] = [
834 'id' => $q,
835 'text' => '',
836 ];
837 }
838
839 wp_send_json(['items' => array_merge($default_items, $items)]);
840 });
841 add_action( 'admin_post_wpc_seo_settings', function() {
842 check_admin_referer( 'wpc_seo_settings' );
843
844 $filter_permalinks = $_POST['wpc_filter_permalinks'] ?? [];
845 $seo_rules_settings = $_POST['wpc_seo_rules_settings'] ?? [];
846 $wpc_indexing_deep_settings = $_POST['wpc_indexing_deep_settings'] ?? [];
847
848 $filter_permalinks = array_map( 'sanitize_text_field', $filter_permalinks );
849 $seo_rules_settings = array_map( 'sanitize_text_field', $seo_rules_settings );
850 $wpc_indexing_deep_settings = array_map( 'sanitize_text_field', $wpc_indexing_deep_settings );
851
852 update_option( 'wpc_filter_permalinks', $filter_permalinks );
853 update_option( 'wpc_seo_rules_settings', $seo_rules_settings );
854 update_option( 'wpc_indexing_deep_settings', $wpc_indexing_deep_settings );
855
856 $redirect_url = add_query_arg( 'settings-updated', 'true', wp_get_referer() );
857 wp_safe_redirect( $redirect_url );
858 exit;
859 });
860
861 if (!defined( 'FLRT_FILTERS_PRO' ) ){
862 add_action( 'admin_footer', function () {
863 if ( ! is_admin() ) {
864 return;
865 }
866
867 $screen = get_current_screen();
868
869 if ( ! $screen ) {
870 return;
871 }
872
873 if ( $screen->post_type === 'filter-set' ) {
874 flrt_include_admin_view('pro-modal', []);
875 }
876 });
877 }
878
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 }
1012
1013 //add_filter( 'stackable/posts/post_query', 'flrt_stackable_block_query_vars', 10, 3 );
1014 //function flrt_stackable_block_query_vars( $post_query, $context, $query_string ){
1015 // if( is_user_logged_in() ) {
1016 // var_dump( $context );
1017 // var_dump( $query_string );
1018 // }
1019 //
1020 // return $post_query;
1021 //}