WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#42471 closed defect (bug) (invalid)

In wp_query, the function parse_search need a remove_placeholder_escape()

Reported by: w.sung Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.8.3
Component: Database Keywords: close
Focuses: Cc:

Description

Hi,

please be patient, this is my first bugreport.

After update to 4.8.3, my results for wp_query with the parameter "s" isn't right anymore. I end up at a $wpdb->prepare() statement. It escapes the "%" with a placeholder. But there should also have a remove_placeholder_escape() to revert it, or not?

It looks like this problem:
https://make.wordpress.org/core/2017/10/31/changed-behaviour-of-esc_sql-in-wordpress-4-8-3/

I hope these are enought information to reproduce it.

File wp-includes/class-wp-query.php
protected function parse_search( &$q )
Near Line: 1354

<?php

                foreach ( $q['search_terms'] as $term ) {
                        // If there is an $exclusion_prefix, terms prefixed with it should be excluded.
                        $exclude = $exclusion_prefix && ( $exclusion_prefix === substr( $term, 0, 1 ) );
                        if ( $exclude ) {
                                $like_op  = 'NOT LIKE';
                                $andor_op = 'AND';
                                $term     = substr( $term, 1 );
                        } else {
                                $like_op  = 'LIKE';
                                $andor_op = 'OR';
                        }
                        if ( $n && ! $exclude ) {
                                $like = '%' . $wpdb->esc_like( $term ) . '%';
                                $q['search_orderby_title'][] = $wpdb->prepare( "{$wpdb->posts}.post_title LIKE %s", $like );
                        }
                        $like = $n . $wpdb->esc_like( $term ) . $n;
                        $search .= $wpdb->prepare( "{$searchand}(({$wpdb->posts}.post_title $like_op %s) $andor_op ({$wpdb->posts}.post_excerpt $like_op %s) $andor_op ({$wpdb->posts}.post_content $like_op %s))", $like, $like, $like );
                        $searchand = ' AND ';
                }

?>

The value of $search looks like:

((wp_posts.post_title LIKE '{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}halo{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}') OR (wp_posts.post_excerpt LIKE '{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}halo{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}') OR (wp_posts.post_content LIKE '{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}halo{f2585b9c225b37a7c261438045c124df961244ec4d1f7a92c10c3aca6fa8d296}'))

Change History (7)

#1 @w.sung
3 years ago

  • Severity changed from normal to major

#2 @w.sung
3 years ago

I forgot the correct result. In 4.8.2 it looks like:

((wp_posts.post_title LIKE '%halo%') OR (wp_posts.post_excerpt LIKE '%halo%') OR (wp_posts.post_content LIKE '%halo%'))

#3 @dd32
3 years ago

  • Component changed from Query to Database
  • Keywords reporter-feedback added
  • Severity changed from major to normal

Hi @w.sung and welcome to Trac.

The change here is expected, and should work properly as-is.
When the $search value is passed to $wpdb->query() the filters there will correct remove the placeholders and perform the expected query against the database.
For reference, here's where the filter is added and used: https://core.trac.wordpress.org/browser/trunk/src/wp-includes/wp-db.php?marks=1789,1959#L1750 (Line 1789 = where the filter is run, 1959 = where the filter is added)

Can you explain what the actual issue you're encountering is?

FWIW, this returns the expected 10 for me: var_dump( (new WP_Query([ 's' => 'testing' ]))->post_count );

#4 @w.sung
3 years ago

  • Keywords close added

Hi @dd32 ,

thank you for your advice. You are right. That wasn't the problem. My problem was, that in 4.8.2 the where-query was like:

WHERE 1=1 AND (((wp_posts.post_title LIKE '%xbox%')) AND ((wp_posts.post_title LIKE '%one%'))) ...

In 4.8.3, I get something like that:

WHERE 1=1 AND (((wp_posts.post_title LIKE '%xbox%') OR (wp_posts.post_excerpt LIKE '%xbox%') OR (wp_posts.post_content LIKE '%xbox%'))) AND (((wp_posts.post_title LIKE '%one%') OR (wp_posts.post_excerpt LIKE '%one%') OR (wp_posts.post_content LIKE '%one%')))

I know now, why my results are different and now I can handle it.

Thanks For Help! Ticket can be closed.

#5 @w.sung
3 years ago

  • Keywords reporter-feedback removed
  • Resolution set to invalid
  • Status changed from new to closed

#6 @dd32
3 years ago

  • Milestone Awaiting Review deleted

Hey @w.sung,
Glad to hear that pointed you in the right direction.

It's possible you've got a plugin installed which isn't compatible with 4.8.3, as the searching logic changed in WordPress 3.7 [25632] to order search results by relevancy, which changed the SQL from your first SQL example to the latter.

#7 @w.sung
3 years ago

Hi @dd32,

I'm using the Plugin "Advance Custom Field". It should be compatible. The problem was, that I got more results as I expected. But now I know what the reason is and I can handle it.

Note: See TracTickets for help on using tickets.