| @@ -37,8 +37,12 @@ | ||
| 37 | 37 | add_action( 'edited_doc_category', array( $this, 'flush_term_counts_cache' ) ); |
| 38 | 38 | add_action( 'created_doc_category', array( $this, 'flush_term_counts_cache' ) ); |
| 39 | 39 | add_action( 'delete_doc_category', array( $this, 'flush_term_counts_cache' ) ); |
| 40 | 40 | add_action( 'set_object_terms', array( $this, 'flush_term_counts_cache_on_set' ), 10, 4 ); |
| 41 | + // wp_update_term_count_now() — the `wp term recount` repair path, and any core | |
| 42 | + // count update — fires edited_term_taxonomy, not any of the above. Without this | |
| 43 | + // the recount fixes the DB while we keep serving the cached counts (#166). | |
| 44 | + add_action( 'edited_term_taxonomy', array( $this, 'flush_term_counts_cache_on_term_taxonomy' ), 10, 2 ); | |
| 41 | 45 | |
| 42 | 46 | /** |
| 43 | 47 | * These below filters are hooked for navigation only. |
| 44 | 48 | * |
| @@ -1278,8 +1282,31 @@ | ||
| 1278 | 1282 | $this->flush_term_counts_cache(); |
| 1279 | 1283 | } |
| 1280 | 1284 | } |
| 1281 | 1285 | |
| 1286 | + /** | |
| 1287 | + * Invalidate the count cache when a term count is recalculated. | |
| 1288 | + * | |
| 1289 | + * wp_update_term_count_now() (a recount, `wp term recount`, or any core count | |
| 1290 | + * update) fires edited_term_taxonomy for each affected term. The version bump is | |
| 1291 | + * a single update_option, so it is debounced to once per request with a static | |
| 1292 | + * flag: one bump already invalidates every cached count, and a bulk recount would | |
| 1293 | + * otherwise write the option once per term. (#166) | |
| 1294 | + * | |
| 1295 | + * @param int $tt_id Term taxonomy id. | |
| 1296 | + * @param string $taxonomy Taxonomy name. | |
| 1297 | + */ | |
| 1298 | + public function flush_term_counts_cache_on_term_taxonomy( $tt_id, $taxonomy ) { | |
| 1299 | + static $flushed = false; | |
| 1300 | + | |
| 1301 | + if ( $flushed || ! in_array( $taxonomy, array( 'doc_category', 'knowledge_base' ), true ) ) { | |
| 1302 | + return; | |
| 1303 | + } | |
| 1304 | + | |
| 1305 | + $this->flush_term_counts_cache(); | |
| 1306 | + $flushed = true; | |
| 1307 | + } | |
| 1308 | + | |
| 1282 | 1309 | public function get_docs_count( $term, $nested_subcategory = false, $args = array() ) { |
| 1283 | 1310 | // Validate term object |
| 1284 | 1311 | if ( ! is_object( $term ) ) { |
| 1285 | 1312 | return 0; |
| @@ -1489,16 +1516,22 @@ | ||
| 1489 | 1516 | } |
| 1490 | 1517 | |
| 1491 | 1518 | global $wpdb; |
| 1492 | 1519 | |
| 1520 | + $keyword_hash = md5( $search_input ); | |
| 1521 | + | |
| 1493 | 1522 | // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- live search-keyword analytics; cache would defeat the purpose. |
| 1494 | - // Use BINARY comparison to avoid collation mismatch errors | |
| 1495 | - // This works across all character sets (latin1, utf8, utf8mb4, etc.) | |
| 1523 | + // Matched on keyword_hash first so the index can serve the lookup — the | |
| 1524 | + // BINARY comparison that follows is what actually decides equality (it | |
| 1525 | + // avoids collation mismatch errors across latin1/utf8/utf8mb4), but no | |
| 1526 | + // index can serve it, so on its own it full-scanned the table on every | |
| 1527 | + // single front-end search. | |
| 1496 | 1528 | $search = $wpdb->get_results( |
| 1497 | 1529 | $wpdb->prepare( |
| 1498 | 1530 | "SELECT * |
| 1499 | 1531 | FROM {$wpdb->prefix}betterdocs_search_keyword |
| 1500 | - WHERE BINARY keyword = %s", | |
| 1532 | + WHERE keyword_hash = %s AND BINARY keyword = %s", | |
| 1533 | + $keyword_hash, | |
| 1501 | 1534 | $search_input |
| 1502 | 1535 | ) |
| 1503 | 1536 | ); |
| 1504 | 1537 | |
| @@ -1557,12 +1590,13 @@ | ||
| 1557 | 1590 | } else { |
| 1558 | 1591 | $insert = $wpdb->query( |
| 1559 | 1592 | $wpdb->prepare( |
| 1560 | 1593 | "INSERT INTO {$wpdb->prefix}betterdocs_search_keyword |
| 1561 | - ( keyword ) | |
| 1562 | - VALUES ( %s )", | |
| 1594 | + ( keyword, keyword_hash ) | |
| 1595 | + VALUES ( %s, %s )", | |
| 1563 | 1596 | array( |
| 1564 | - $search_input | |
| 1597 | + $search_input, | |
| 1598 | + $keyword_hash | |
| 1565 | 1599 | ) |
| 1566 | 1600 | ) |
| 1567 | 1601 | ); |
| 1568 | 1602 | |