diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index e39739883e..b154ff0320 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -2994,7 +2994,7 @@ function wp_ajax_query_attachments() { // Filter query clauses to include filenames. if ( isset( $query['s'] ) ) { - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); } /** diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index f3300fcf1e..bc034869af 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -1302,7 +1302,7 @@ function wp_edit_attachments_query_vars( $q = false ) { // Filter query clauses to include filenames. if ( isset( $q['s'] ) ) { - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); } return $q; diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index e7eda7bab7..edf6799cb6 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -444,6 +444,14 @@ class WP_Query { */ public $thumbnails_cached = false; + /** + * Controls whether an attachment query should include filenames or not. + * + * @since 6.0.3 + * @var bool + */ + protected $allow_query_attachment_by_filename = false; + /** * Cached list of search stopwords. * @@ -1414,8 +1422,13 @@ class WP_Query { $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 ); + $like = $n . $wpdb->esc_like( $term ) . $n; + + if ( ! empty( $this->allow_query_attachment_by_filename ) ) { + $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) $andor_op (sq1.meta_value $like_op %s))", $like, $like, $like, $like ); + } else { + $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 '; } @@ -1810,6 +1823,16 @@ class WP_Query { // Fill again in case 'pre_get_posts' unset some vars. $q = $this->fill_query_vars( $q ); + /** + * Filters whether an attachment query should include filenames or not. + * + * @since 6.0.3 + * + * @param bool $allow_query_attachment_by_filename Whether or not to include filenames. + */ + $this->allow_query_attachment_by_filename = apply_filters( 'wp_allow_query_attachment_by_filename', false ); + remove_all_filters( 'wp_allow_query_attachment_by_filename' ); + // Parse meta query. $this->meta_query = new WP_Meta_Query(); $this->meta_query->parse_query_vars( $q ); @@ -2241,7 +2264,7 @@ class WP_Query { } } - if ( ! empty( $this->tax_query->queries ) || ! empty( $this->meta_query->queries ) ) { + if ( ! empty( $this->tax_query->queries ) || ! empty( $this->meta_query->queries ) || ! empty( $this->allow_query_attachment_by_filename ) ) { $groupby = "{$wpdb->posts}.ID"; } @@ -2318,6 +2341,10 @@ class WP_Query { } $where .= $search . $whichauthor . $whichmimetype; + if ( ! empty( $this->allow_query_attachment_by_filename ) ) { + $join .= " LEFT JOIN {$wpdb->postmeta} AS sq1 ON ( {$wpdb->posts}.ID = sq1.post_id AND sq1.meta_key = '_wp_attached_file' )"; + } + if ( ! empty( $this->meta_query->queries ) ) { $clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this ); $join .= $clauses['join']; diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index ec4c4678f5..013694391c 100644 --- a/src/wp-includes/deprecated.php +++ b/src/wp-includes/deprecated.php @@ -4311,3 +4311,20 @@ function wp_skip_spacing_serialization( $block_type ) { function wp_add_iframed_editor_assets_html() { _deprecated_function( __FUNCTION__, '6.0.0' ); } + +/** + * Filter the SQL clauses of an attachment query to include filenames. + * + * @since 4.7.0 + * @deprecated 6.0.3 + * @access private + * + * @param array $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY, + * DISTINCT, fields (SELECT), and LIMITS clauses. + * @return array The unmodified clauses. + */ +function _filter_query_attachment_filenames( $clauses ) { + _deprecated_function( __FUNCTION__, '4.9.9', 'add_filter( "wp_allow_query_attachment_by_filename", "__return_true" )' ); + remove_filter( 'posts_clauses', __FUNCTION__ ); + return $clauses; +} \ No newline at end of file diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 288704c66d..e7abb6feda 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -7918,36 +7918,6 @@ function wp_add_trashed_suffix_to_post_name_for_post( $post ) { return $post_name; } -/** - * Filters the SQL clauses of an attachment query to include filenames. - * - * @since 4.7.0 - * @access private - * - * @global wpdb $wpdb WordPress database abstraction object. - * - * @param string[] $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY, - * DISTINCT, fields (SELECT), and LIMITS clauses. - * @return string[] The modified array of clauses. - */ -function _filter_query_attachment_filenames( $clauses ) { - global $wpdb; - remove_filter( 'posts_clauses', __FUNCTION__ ); - - // Add a LEFT JOIN of the postmeta table so we don't trample existing JOINs. - $clauses['join'] .= " LEFT JOIN {$wpdb->postmeta} AS sq1 ON ( {$wpdb->posts}.ID = sq1.post_id AND sq1.meta_key = '_wp_attached_file' )"; - - $clauses['groupby'] = "{$wpdb->posts}.ID"; - - $clauses['where'] = preg_replace( - "/\({$wpdb->posts}.post_content (NOT LIKE|LIKE) (\'[^']+\')\)/", - '$0 OR ( sq1.meta_value $1 $2 )', - $clauses['where'] - ); - - return $clauses; -} - /** * Sets the last changed time for the 'posts' cache group. * diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index 423347a721..ff3c1dc42f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -97,7 +97,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { // Filter query clauses to include filenames. if ( isset( $query_args['s'] ) ) { - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); } return $query_args; diff --git a/tests/phpunit/tests/query/search.php b/tests/phpunit/tests/query/search.php index 418acbfc85..5a7eab28c0 100644 --- a/tests/phpunit/tests/query/search.php +++ b/tests/phpunit/tests/query/search.php @@ -454,7 +454,7 @@ class Tests_Query_Search extends WP_UnitTestCase { ); add_post_meta( $attachment, '_wp_attached_file', 'some-image1.png', true ); - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); // Pass post_type a string value. $q = new WP_Query( @@ -484,7 +484,7 @@ class Tests_Query_Search extends WP_UnitTestCase { ); add_post_meta( $attachment, '_wp_attached_file', 'some-image2.png', true ); - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); // Pass post_type an array value. $q = new WP_Query( @@ -543,7 +543,7 @@ class Tests_Query_Search extends WP_UnitTestCase { add_post_meta( $attachment, '_wp_attached_file', 'some-image4.png', true ); add_post_meta( $attachment, '_test_meta_key', 'value', true ); - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); // Pass post_type a string value. $q = new WP_Query( @@ -583,7 +583,7 @@ class Tests_Query_Search extends WP_UnitTestCase { wp_set_post_terms( $attachment, 'test', 'post_tag' ); add_post_meta( $attachment, '_wp_attached_file', 'some-image5.png', true ); - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); // Pass post_type a string value. $q = new WP_Query( @@ -608,25 +608,37 @@ class Tests_Query_Search extends WP_UnitTestCase { /** * @ticket 22744 */ - public function test_filter_query_attachment_filenames_unhooks_itself() { - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); - - apply_filters( - 'posts_clauses', + public function test_wp_query_removes_filter_wp_allow_query_attachment_by_filename() { + $attachment = self::factory()->post->create( array( - 'where' => '', - 'groupby' => '', - 'join' => '', - 'orderby' => '', - 'distinct' => '', - 'fields' => '', - 'limit' => '', + 'post_type' => 'attachment', + 'post_status' => 'publish', + 'post_title' => 'bar foo', + 'post_content' => 'foo bar', + 'post_excerpt' => 'This post has foo', ) ); - $result = has_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + add_post_meta( $attachment, '_wp_attached_file', 'some-image1.png', true ); + add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' ); - $this->assertFalse( $result ); + $q = new WP_Query( + array( + 's' => 'image1', + 'fields' => 'ids', + 'post_type' => 'attachment', + 'post_status' => 'inherit', + ) + ); + + $this->assertSame( array( $attachment ), $q->posts ); + + /* + * WP_Query should have removed the wp_allow_query_attachment_by_filename filter + * and thus not match the attachment created above. + */ + $q->get_posts(); + $this->assertEmpty( $q->posts ); } public function filter_posts_search( $sql ) {