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/Admin/FilterSet.php +117 -14 1.9.2.11.9.7 View file →
@@ -12,8 +12,14 @@
12 12 const NONCE_ACTION = 'wpc-f-set-nonce';
13 13
14 14 const FIELD_NAME_PREFIX = 'wpc_set_fields';
15 15
16 + const FREE_LIMIT_NEW = 2;
17 +
18 + const FREE_LIMIT_LEGACY = 3;
19 +
20 + const FREE_LIMIT_CUTOFF_DATE = '2026-06-15 00:00:00';
21 +
16 22 private $defaultFields = [];
17 23
18 24 private $hooksRegistered = false;
19 25
@@ -307,8 +313,19 @@
307 313 'defaultCustomMetaKeys' => wpc_default_custom_meta_keys_filter(),
308 314 'selectMetaKeyPlaceholder' => esc_html__( 'Type to search for a custom field key', 'filter-everything' ),
309 315 'metaKeySearchText' => esc_html__( 'Searching', 'filter-everything' ),
310 316 'isLimitFilterSet' => $this->under_limit_filter_set($post_id),
317 + 'rangeListValueToRemove' => esc_html__('Remove', 'filter-everything'),
318 + 'limitForRangeList' => (int)(defined('FLRT_RANGE_LIST_LIMIT') && FLRT_RANGE_LIST_LIMIT) ? FLRT_RANGE_LIST_LIMIT : 20,
319 + 'rangeListTexts' => [
320 + 'min_value' => esc_html__('Min Value', 'filter-everything'),
321 + 'max_value' => esc_html__('Max Value', 'filter-everything'),
322 + 'label' => esc_html__('Label', 'filter-everything'),
323 + 'up_to' => esc_html__('Up to', 'filter-everything'),
324 + 'and_up' => esc_html__('And up', 'filter-everything'),
325 + 'error' => esc_html__('Error: No fields are filled in. Please fill in at least one field.', 'filter-everything'),
326 + 'value_error' => esc_html__('Error: The minimum value cannot be greater than or equal to the maximum value.', 'filter-everything'),
327 + ],
311 328 );
312 329
313 330 wp_localize_script( 'wpc-filters-admin-filter-set', 'wpcSetVars', $l10n );
314 331 }
@@ -426,8 +443,9 @@
426 443
427 444 if( ! empty( $filterSets ) ){
428 445 foreach ( $filterSets as $set ){
429 446 if( isset( $set['show_on_the_page'] ) && $set['show_on_the_page'] === true ){
447 + $this->addFilterSetsToJsonData($filterSets);
430 448 return $filterSets;
431 449 }
432 450 }
433 451 }
@@ -443,8 +461,10 @@
443 461 }
444 462
445 463 $filterSets = apply_filters( 'wpc_return_relevant_set_ids', $filterSets, $queriedObject );
446 464
465 + $this->addFilterSetsToJsonData($filterSets);
466 +
447 467 return $filterSets;
448 468 }
449 469
450 470 /**
@@ -574,8 +594,9 @@
574 594
575 595 public function preSaveSet( $post_id, $data )
576 596 {
577 597 $postData = Container::instance()->getThePost();
598 + $postData = prepare_wpc_filter_set_json_data($postData);
578 599
579 600 if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
580 601 return $post_id;
581 602 }
@@ -623,8 +644,10 @@
623 644
624 645 public function saveSet( $post_id, $post )
625 646 {
626 647 $postData = Container::instance()->getThePost();
648 + $postData = prepare_wpc_filter_set_json_data($postData);
649 +
627 650 if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
628 651 return $post_id;
629 652 }
630 653
@@ -1089,10 +1112,12 @@
1089 1112 }
1090 1113
1091 1114 public function getPostTypeField( $post_id )
1092 1115 {
1116 + // getSet() returns [] for an empty ID (e.g. a Filters block/widget with
1117 + // no Filter Set chosen) — report "no post type" instead of a warning.
1093 1118 $set = $this->getSet( $post_id );
1094 - $field['post_type'] = ( $set['post_type'] ) ? $set['post_type'] : NULL;
1119 + $field['post_type'] = ! empty( $set['post_type'] ) ? $set['post_type'] : NULL;
1095 1120 return $field;
1096 1121 }
1097 1122
1098 1123 public function getSettingsTypeFields( $post_id )
@@ -1363,8 +1388,65 @@
1363 1388 $content = maybe_unserialize($raw);
1364 1389 return is_array($content) ? $content : [];
1365 1390 }
1366 1391
1392 + /**
1393 + * Returns the effective free-version Filter Set limit for a given post type.
1394 + *
1395 + * The historical free limit was {@see self::FREE_LIMIT_LEGACY} (3) Filter Sets per post type.
1396 + * From {@see self::FREE_LIMIT_CUTOFF_DATE} onwards the new free limit is {@see self::FREE_LIMIT_NEW} (2).
1397 + * To avoid breaking existing free-version installs that already relied on the old limit, any post type
1398 + * that had at least one published Filter Set created before the cutoff is grandfathered at the legacy
1399 + * limit; only post types whose Filter Sets are all post-cutoff (or have none yet) get the new lower limit.
1400 + *
1401 + * @param string $post_type Target post type (stored in wp_posts.post_excerpt for Filter Sets).
1402 + * @return int Effective max number of published Filter Sets allowed for this post type.
1403 + */
1404 + public function getFreeLimitForPostType($post_type) : int
1405 + {
1406 + if (empty($post_type)) {
1407 + return self::FREE_LIMIT_NEW;
1408 + }
1409 +
1410 + global $wpdb;
1411 +
1412 + $legacy_count = (int) $wpdb->get_var(
1413 + $wpdb->prepare(
1414 + "SELECT COUNT(ID)
1415 + FROM {$wpdb->posts}
1416 + WHERE post_type = %s
1417 + AND post_excerpt = %s
1418 + AND post_status = %s
1419 + AND post_date < %s",
1420 + FLRT_FILTERS_SET_POST_TYPE,
1421 + $post_type,
1422 + 'publish',
1423 + self::FREE_LIMIT_CUTOFF_DATE
1424 + )
1425 + );
1426 +
1427 + return $legacy_count > 0 ? self::FREE_LIMIT_LEGACY : self::FREE_LIMIT_NEW;
1428 + }
1429 +
1430 + /**
1431 + * Checks whether the free-version limit of published Filter Sets per post type has been reached.
1432 + *
1433 + * In the PRO version (FLRT_FILTERS_PRO is defined and true) the limit does not apply and the method
1434 + * always returns false. In the free version the effective limit comes from {@see self::getFreeLimitForPostType()}
1435 + * — {@see self::FREE_LIMIT_LEGACY} (3) for post types grandfathered by Filter Sets created before
1436 + * {@see self::FREE_LIMIT_CUTOFF_DATE}, and {@see self::FREE_LIMIT_NEW} (2) otherwise. The method then:
1437 + * - resolves the post type from $post_id (or $default_post_type if provided),
1438 + * - returns true (over the limit) when there are already enough Filter Sets for that post type and
1439 + * the current $post_id is not among the first allowed ones, when switching an existing set to a
1440 + * post type that already has enough sets, or when no Filter Set context exists yet and the
1441 + * post type already has enough sets,
1442 + * - returns false otherwise, i.e. the user is still under the limit and may proceed.
1443 + *
1444 + * @param int|string $post_id ID of the Filter Set being edited, or empty when creating a new one.
1445 + * @param string $default_post_type Post type explicitly chosen in the UI; overrides the value stored on the set.
1446 + * @param bool $update Reserved flag for update flows (currently unused inside the method).
1447 + * @return bool True when the free-version limit is reached and the action must be blocked, false otherwise.
1448 + */
1367 1449 public function under_limit_filter_set($post_id = '', $default_post_type = '', $update = false) : bool
1368 1450 {
1369 1451
1370 1452 if( defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO ){
@@ -1390,14 +1472,16 @@
1390 1472 $post_type = $default_post_type;
1391 1473 }
1392 1474
1393 1475 if (!empty($post_type)) {
1476 + $limit = $this->getFreeLimitForPostType($post_type);
1477 +
1394 1478 $count = $wpdb->get_var(
1395 1479 $wpdb->prepare(
1396 - "SELECT COUNT(ID)
1397 - FROM {$wpdb->posts}
1398 - WHERE post_type = %s
1399 - AND post_excerpt = %s
1480 + "SELECT COUNT(ID)
1481 + FROM {$wpdb->posts}
1482 + WHERE post_type = %s
1483 + AND post_excerpt = %s
1400 1484 AND post_status = %s",
1401 1485 FLRT_FILTERS_SET_POST_TYPE,
1402 1486 $post_type,
1403 1487 'publish',
@@ -1405,23 +1489,24 @@
1405 1489 );
1406 1490
1407 1491 $post_ids = $wpdb->get_col(
1408 1492 $wpdb->prepare(
1409 - "SELECT ID
1410 - FROM {$wpdb->posts}
1411 - WHERE post_type = %s
1412 - AND post_excerpt = %s
1493 + "SELECT ID
1494 + FROM {$wpdb->posts}
1495 + WHERE post_type = %s
1496 + AND post_excerpt = %s
1413 1497 AND post_status = %s
1414 1498 ORDER BY ID ASC
1415 - LIMIT 3",
1499 + LIMIT %d",
1416 1500 FLRT_FILTERS_SET_POST_TYPE,
1417 1501 $post_type,
1418 - 'publish'
1502 + 'publish',
1503 + $limit
1419 1504 )
1420 1505 );
1421 1506
1422 1507 if (!empty($post_id)) {
1423 - if ($count >= 3 && !in_array($post_id, $post_ids)) {
1508 + if ($count >= $limit && !in_array($post_id, $post_ids)) {
1424 1509 return true;
1425 1510 }
1426 1511 }
1427 1512
@@ -1432,15 +1517,15 @@
1432 1517 }
1433 1518
1434 1519 if(!empty($default_post_type) && !empty($get_post_type['post_type']['value'])){
1435 1520 if($default_post_type !== $get_post_type['post_type']['value']){
1436 - if($count >= 3){
1521 + if($count >= $limit){
1437 1522 return true;
1438 1523 }
1439 1524 }
1440 1525 }
1441 1526
1442 - if(empty($get_post_type['post_type']['value']) && $count >= 3){
1527 + if(empty($get_post_type['post_type']['value']) && $count >= $limit){
1443 1528 return true;
1444 1529 }
1445 1530
1446 1531 }
@@ -1449,6 +1534,24 @@
1449 1534 }
1450 1535
1451 1536 public function getErrors() {
1452 1537 return $this->errors;
1538 + }
1539 +
1540 + private function addFilterSetsToJsonData($filterSets)
1541 + {
1542 + $flrt_json_data = &Container::instance()->getFilterContext()->jsonData();
1543 + foreach ($filterSets as $set) {
1544 + $setId = $set['ID'];
1545 + $setSettings = $this->getSet($setId);
1546 +
1547 + if(!isset($flrt_json_data[$setId])){
1548 + $flrt_json_data[$setId] = [];
1549 + }
1550 +
1551 + $flrt_json_data[$setId]['settings'] = array_map(
1552 + fn($item) => is_array($item) ? $item['value'] : $item,
1553 + $setSettings
1554 + );
1555 + }
1453 1556 }
1454 1557 }