BUG: Search::integrate_search_queries() overrides explicit 'ep_integrate' => true with return false in AJAX and Admin requests

Open Beginner friendly
#4,402 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
php, wordpress
Domain
backend, search

Research direction

Start with includes/classes/Feature/Search/Search.php, especially integrate_search_queries(), and compare its early return with the $enabled handling described in includes/classes/Indexable.php. Check the existing tests for search integration in admin and AJAX requests, then add coverage for an explicitly enabled ep_integrate query. Done when that query remains enabled in those contexts and the relevant tests pass.

Written by the indexing model from the issue text.

Description

bug
Describe the bug

Hello ElasticPress Team,

We found a bug in ElasticPress\Feature\Search\Search::integrate_search_queries() (in includes/classes/Feature/Search/Search.php, lines 579-582, tested on v5.3.5) where explicitly passing 'ep_integrate' => true to WP_Query during an admin-ajax.php (DOING_AJAX) or wp-admin request is ignored and overridden with false.

  1. How it happens:
    In ElasticPress\Indexable::elasticpress_enabled( $query ) (includes/classes/Indexable.php, lines 728-742):

    public function elasticpress_enabled( $query ) {
    $enabled = false;

     if ( ! empty( $query->query_vars['ep_integrate'] ) ) {
         $enabled = true;
     }
    
     $enabled = apply_filters( 'ep_elasticpress_enabled', $enabled, $query );
    

Here, $enabled is properly set to true when a developer explicitly passes 'ep_integrate' => true to WP_Query.

However, Search::integrate_search_queries( $enabled, $query ) is hooked into ep_elasticpress_enabled (Search.php, line 118) and starts with:

public function integrate_search_queries( $enabled, $query ) {
    if ( ! Utils\is_integrated_request( $this->slug ) ) {
        return false;
    }

    if ( ! is_a( $query, 'WP_Query' ) ) {
        return $enabled;
    }

In Utils\is_integrated_request(), both $is_integrated_admin_request and $is_integrated_ajax_request default to false unless the ep_admin_wp_query_integration or ep_ajax_wp_query_integration filters return true.

Because line 581 returns hardcoded false instead of return $enabled;, any custom WP_Query in an admin-ajax.php handler or wp-admin screen that explicitly sets 'ep_integrate' => true gets forced back to false and silently falls back to MySQL!

  1. Suggested Fix:
    In includes/classes/Feature/Search/Search.php (line 581), change "return false;" to "return $enabled;":

    if ( ! Utils\is_integrated_request( $this->slug ) ) {
    return $enabled;
    }

This way, automatic search integration still respects Utils\is_integrated_request(), while queries that explicitly pass 'ep_integrate' => true are not broken in wp-admin or admin-ajax.php.

Thank you!

Steps to Reproduce
  1. Activate ElasticPress and index posts on a WordPress site (keep default settings where ep_ajax_wp_query_integration and ep_admin_wp_query_integration filters are not enabled).

  2. Register a custom wp-admin AJAX action (or run via WP-CLI simulating an AJAX request) that creates a WP_Query with 'ep_integrate' => true:

    add_action( 'wp_ajax_my_custom_ep_search', function() {
    $query = new WP_Query( array(
    'post_type' => 'post',
    'post_status' => 'publish',
    's' => 'test',
    'ep_integrate' => true,
    ) );
    wp_send_json( array(
    'ep_enabled' => \ElasticPress\Indexables::factory()->get( 'post' )->elasticpress_enabled( $query ),
    'ep_success' => ! empty( $query->elasticsearch_success ),
    ) );
    } );

  3. Call the AJAX endpoint: /wp-admin/admin-ajax.php?action=my_custom_ep_search (or run in WP-CLI: wp eval 'define("DOING_AJAX", true); set_current_screen("admin-ajax"); $q = new WP_Query(["post_type" => "post", "s" => "test", "ep_integrate" => true]); var_dump($q->elasticsearch_success);').

  4. Observe that $query->elasticsearch_success is null/false and the query runs against MySQL instead of Elasticsearch.

Expected behavior:
When a developer explicitly passes 'ep_integrate' => true to WP_Query, ElasticPress should integrate and run that specific query against Elasticsearch regardless of whether it is executed in a frontend, wp-admin, or admin-ajax.php context.

Actual behavior:

  1. In ElasticPress\Indexable::elasticpress_enabled( $query ) (includes/classes/Indexable.php, lines 728-742), $enabled is set to true because $query->query_vars['ep_integrate'] is true, and then passed to apply_filters( 'ep_elasticpress_enabled', $enabled, $query ).
  2. However, ElasticPress\Feature\Search\Search::integrate_search_queries( $enabled, $query ) is hooked into ep_elasticpress_enabled (includes/classes/Feature/Search/Search.php, line 118) and starts with (lines 579-582):
Screenshots, screen recording, code snippet

No response

Environment information

No response

WordPress and ElasticPress information

No response

Code of Conduct
  • I agree to follow this project's Code of Conduct
Dominant language
PHP
Stars
1.3k
Forks
325
Avg merge
2d 12h
Merged PRs (30d)
19

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from 10up/ElasticPress

All issues in 10up/ElasticPress

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.