From b97899a07fe8bc44ccdc4700f7956c06bf11e6f7 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 1 Jul 2019 20:47:21 +0000 Subject: [PATCH] Taxonomy: add a new 'terms_pre_query' filter to short circuit WP_Term_Query 'get_terms' queries. Add a new `terms_pre_query` filter which returns null by default. Return a non-null value to bypass WordPress's default `get_terms` queries. Props jarocks, boonebgorges, spacedmonkey. Fixes #41246. git-svn-id: https://develop.svn.wordpress.org/trunk@45584 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-term-query.php | 20 +++++++++++++++++ tests/phpunit/tests/term/query.php | 30 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/wp-includes/class-wp-term-query.php b/src/wp-includes/class-wp-term-query.php index 4b949c6e16..b2bf518995 100644 --- a/src/wp-includes/class-wp-term-query.php +++ b/src/wp-includes/class-wp-term-query.php @@ -672,6 +672,26 @@ class WP_Term_Query { $this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}"; + $this->terms = null; + + /** + * Filter the terms array before the query takes place. + * + * Return a non-null value to bypass WordPress's default term queries. + * + * @since 5.3.0 + * + * @param array|null $terms Return an array of term data to short-circuit WP's term query, + * or null to allow WP queries to run normally. + * @param WP_Term_Query $this The WP_Term_Query instance, passed by reference. + * + */ + $this->terms = apply_filters_ref_array( 'terms_pre_query', array( $this->terms, &$this ) ); + + if ( null !== $this->terms ) { + return $this->terms; + } + // $args can be anything. Only use the args defined in defaults to compute the key. $key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request ); $last_changed = wp_cache_get_last_changed( 'terms' ); diff --git a/tests/phpunit/tests/term/query.php b/tests/phpunit/tests/term/query.php index f40a9b55e7..4daac1c35f 100644 --- a/tests/phpunit/tests/term/query.php +++ b/tests/phpunit/tests/term/query.php @@ -737,4 +737,34 @@ class Tests_Term_Query extends WP_UnitTestCase { return $term; } + + /** + * @ticket 41246 + */ + public function test_terms_pre_query_filter_should_bypass_database_query() { + global $wpdb; + + add_filter( 'terms_pre_query', array( __CLASS__, 'filter_terms_pre_query' ), 10, 2 ); + + $num_queries = $wpdb->num_queries; + + $q = new WP_Term_Query(); + $results = $q->query( + array( + 'fields' => 'ids', + ) + ); + + remove_filter( 'terms_pre_query', array( __CLASS__, 'filter_terms_pre_query' ), 10, 2 ); + + // Make sure no queries were executed. + $this->assertSame( $num_queries, $wpdb->num_queries ); + + // We manually inserted a non-existing term and overrode the results with it. + $this->assertSame( array( 555 ), $q->terms ); + } + + public static function filter_terms_pre_query( $terms, $query ) { + return array( 555 ); + } }