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/Entities/TaxonomyEntity.php +86 -6 1.9.2.11.9.7 View file →
@@ -8,9 +8,17 @@
8 8
9 9 class TaxonomyEntity implements Entity
10 10 {
11 11 public $items = [];
12 + /**
13 + * Declared explicitly: assigned from the outside in
14 + * EntityManager::prepareEntitiesToDisplay(); dynamic properties are
15 + * deprecated since PHP 8.2.
16 + */
17 + public $items_sort = [];
12 18
19 + public $filter = [];
20 +
13 21 public $excludedTerms = [];
14 22
15 23 public $isInclude = false;
16 24
@@ -84,10 +92,24 @@
84 92
85 93 // Check if it is already stored
86 94 $transient_key = flrt_get_post_ids_transient_key( $filter['slug'] );
87 95
88 - if ( false === ( $results = flrt_get_transient( $transient_key ) ) ) {
96 + $ids = flrt_get_transient( $transient_key );
89 97
98 + // Cache format v2: aggregated [term_id => [object_id, ...]] int map.
99 + // Legacy format cached raw SQL rows (each an assoc array with a 'term_id'
100 + // key) — detect and rebuild those. The compact map is 15-30x smaller in
101 + // memory and in wp_options.
102 + $is_v2 = is_array( $ids );
103 + if ( $is_v2 && ! empty( $ids ) ) {
104 + $first_item = reset( $ids );
105 + if ( is_array( $first_item ) && isset( $first_item['term_id'] ) ) {
106 + $is_v2 = false;
107 + }
108 + }
109 +
110 + if ( ! $is_v2 ) {
111 +
90 112 // It wasn't there, so regenerate the data and save the transient
91 113 if( defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO ) {
92 114 if( strpos( $this->getName(), 'pa_' ) === 0 ) {
93 115 $include_variation_atts = true;
@@ -116,15 +138,20 @@
116 138 $query = implode(' ', $query);
117 139
118 140 $results = $wpdb->get_results($query, ARRAY_A);
119 141
120 - flrt_set_transient( $transient_key, $results, FLRT_TRANSIENT_PERIOD_HOURS * HOUR_IN_SECONDS );
121 - }
142 + // Note: with the v2 cache this filter runs on the raw rows only when
143 + // the cache is being (re)built, not on every request as before.
144 + $taxonomy_terms = apply_filters( 'wpc_term_taxonomy_terms', $results, $this );
145 + unset( $results );
122 146
123 - $taxonomy_terms = apply_filters( 'wpc_term_taxonomy_terms', $results, $this );
147 + $ids = [];
148 + foreach ($taxonomy_terms as $key => $result) {
149 + $ids[ (int) $result['term_id'] ][] = (int) $result['object_id'];
150 + }
151 + unset( $taxonomy_terms );
124 152
125 - foreach ($taxonomy_terms as $key => $result) {
126 - $ids[$result['term_id']][] = (int) $result['object_id'];
153 + flrt_set_transient( $transient_key, $ids, FLRT_TRANSIENT_PERIOD_HOURS * HOUR_IN_SECONDS );
127 154 }
128 155
129 156 // Add possible empty terms without posts
130 157 foreach( $termIds as $term_id ){
@@ -190,8 +217,29 @@
190 217 $wpManager = Container::instance()->getWpManager();
191 218 $wp_queried_object = $wpManager->getQueryVar( 'wp_queried_object' );
192 219 $wp_queried_term_id = ( isset( $wp_queried_object['term_id'] ) && $wp_queried_object['term_id'] > 0 ) ? $wp_queried_object['term_id'] : 0;
193 220
221 + // On shops that list variations as standalone products (e.g. XStore's
222 + // "variable_products_detach") the set universe contains VARIATIONS while
223 + // the variable parents are excluded via post__not_in. Term relationships,
224 + // however, live on the parents — a plain intersection below would drop
225 + // them and zero out every taxonomy counter. Treat a parent as
226 + // "in universe" when any of its variations is: map the in-universe
227 + // variations back to their parents (PRO hooks mapVariationIdsToParentIds
228 + // here; in the free build the filter is a no-op) and union both lists.
229 + // NOTE: this deliberately uses the UNGATED mapping filter — the parent
230 + // identity is needed here regardless of how the catalog lists its items,
231 + // while wpc_from_variations_to_products is a counting-time collapse that
232 + // stays off on variations-as-products shops.
233 + // The wpc_items_before_calc_term_count replacement later turns parents
234 + // back into their variations, and calcTermCount() intersects against the
235 + // real universe again, so the final counts stay exact. On sites whose
236 + // universe holds no variation IDs the union changes nothing.
237 + $universeParents = apply_filters( 'wpc_variations_to_parents_always', $allWpQueriedPostIds );
238 + if ( is_array( $universeParents ) && $universeParents !== $allWpQueriedPostIds ) {
239 + $allWpQueriedPostIds = array_merge( $allWpQueriedPostIds, $universeParents );
240 + }
241 +
194 242 $allWpQueriedPostIds = array_flip( $allWpQueriedPostIds );
195 243
196 244 foreach( $this->items as $index => $term ) {
197 245 if( isset( $termPosts[$term->term_id] ) ) {
@@ -447,8 +495,40 @@
447 495 'taxonomy' => $queried_value['e_name'],
448 496 'field' => 'slug',
449 497 'terms' => $queried_value['values'],
450 498 );
499 +
500 + /**
501 + * On multilingual sites, resolve slugs to term IDs of the current language
502 + * before querying.
503 + *
504 + * With Polylang / WPML a single slug can belong to several terms in
505 + * different languages (e.g. an English "leather" term and a Latvian one
506 + * sharing the slug "leather"). Querying by slug then matches the
507 + * wrong-language term, which makes Polylang fire a canonical 301 redirect.
508 + * getTermId() resolves against getAllExistingTerms(), which is already
509 + * scoped to the active language, so the query targets the right term.
510 + * Falls back to slug matching if any value can't be resolved.
511 + *
512 + * Gated to multilingual setups so single-language sites keep the original
513 + * slug-based path untouched (no extra term lookups).
514 + */
515 + if ( function_exists( 'pll_current_language' ) || flrt_wpml_active() ) {
516 + $term_ids = array();
517 + foreach ( (array) $queried_value['values'] as $term_slug ) {
518 + $term_id = $this->getTermId( $term_slug );
519 + if ( ! $term_id ) {
520 + $term_ids = array();
521 + break;
522 + }
523 + $term_ids[] = $term_id;
524 + }
525 +
526 + if ( ! empty( $term_ids ) ) {
527 + $args['field'] = 'term_id';
528 + $args['terms'] = $term_ids;
529 + }
530 + }
451 531
452 532 if( isset( $queried_value['logic'] ) && $queried_value['logic'] === 'and' ){
453 533 $args['include_children'] = false;
454 534 }