From 2eade6230df18671328fe0862eb82e15c170a00e Mon Sep 17 00:00:00 2001 From: joemcgill Date: Wed, 5 Oct 2016 19:50:02 +0000 Subject: [PATCH] Media: Better handling of JOINs when searching filenames. Following [38625], any media searches that already included JOINs, e.g., `tax_queries`, would get trampled when we joined the post meta table to search for filenames. This preserves existing JOINs and also only applies the `_filter_query_attachment_filenames()` filter when a search query is being performed. Props flixos90, joemcgill. Fixes #22744. git-svn-id: https://develop.svn.wordpress.org/trunk@38733 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/ajax-actions.php | 4 +- src/wp-admin/includes/post.php | 10 ++- tests/phpunit/tests/query/search.php | 91 ++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index cc9fa432fc..f3799b4ec3 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -2401,7 +2401,9 @@ function wp_ajax_query_attachments() { $query['post_status'] .= ',private'; // Filter query clauses to include filenames. - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + if ( isset( $query['s'] ) ) { + add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + } /** * Filters the arguments passed to WP_Query during an Ajax diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index b12aa5d070..c352cbc91f 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -1145,7 +1145,9 @@ function wp_edit_attachments_query_vars( $q = false ) { } // Filter query clauses to include filenames. - add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + if ( isset( $q['s'] ) ) { + add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + } return $q; } @@ -1164,12 +1166,14 @@ function _filter_query_attachment_filenames( $clauses ) { global $wpdb; remove_filter( 'posts_clauses', __FUNCTION__ ); - $clauses['join'] = " INNER JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id )"; + // 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 ( {$wpdb->postmeta}.meta_key = '_wp_attached_file' AND {$wpdb->postmeta}.meta_value $1 $2 )", + "$0 OR ( sq1.meta_value $1 $2 )", $clauses['where'] ); return $clauses; diff --git a/tests/phpunit/tests/query/search.php b/tests/phpunit/tests/query/search.php index d0a34a67cb..2931a1a731 100644 --- a/tests/phpunit/tests/query/search.php +++ b/tests/phpunit/tests/query/search.php @@ -384,6 +384,97 @@ class Tests_Query_Search extends WP_UnitTestCase { $this->assertNotEquals( array( $attachment ), $q->posts ); } + /** + * @ticket 22744 + */ + public function test_include_file_names_in_attachment_search_with_meta_query() { + $attachment = self::factory()->post->create( array( + 'post_type' => 'attachment', + 'post_status' => 'publish', + 'post_title' => 'bar foo', + 'post_content' => 'foo bar', + 'post_excerpt' => 'This post has foo', + ) ); + + 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' ); + + // Pass post_type a string value. + $q = new WP_Query( array( + 's' => 'image4', + 'fields' => 'ids', + 'post_type' => 'attachment', + 'post_status' => 'inherit', + 'meta_query' => array( + array( + 'key' => '_test_meta_key', + 'value' => 'value', + 'compare' => '=', + ), + ), + ) ); + + $this->assertSame( array( $attachment ), $q->posts ); + } + + /** + * @ticket 22744 + */ + public function test_include_file_names_in_attachment_search_with_tax_query() { + $attachment = self::factory()->post->create( array( + 'post_type' => 'attachment', + 'post_status' => 'publish', + 'post_title' => 'bar foo', + 'post_content' => 'foo bar', + 'post_excerpt' => 'This post has foo', + ) ); + + // Add a tag to the post. + 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' ); + + // Pass post_type a string value. + $q = new WP_Query( array( + 's' => 'image5', + 'fields' => 'ids', + 'post_type' => 'attachment', + 'post_status' => 'inherit', + 'tax_query' => array( + array( + 'taxonomy' => 'post_tag', + 'field' => 'slug', + 'terms' => 'test', + ), + ), + ) ); + + $this->assertSame( array( $attachment ), $q->posts ); + } + + /** + * @ticket 22744 + */ + public function test_filter_query_attachment_filenames_unhooks_itself() { + add_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + + apply_filters( 'posts_clauses', array( + 'where' => '', + 'groupby' => '', + 'join' => '', + 'orderby' => '', + 'distinct' => '', + 'fields' => '', + 'limit' => '', + ) ); + + $result = has_filter( 'posts_clauses', '_filter_query_attachment_filenames' ); + + $this->assertFalse( $result ); + } + public function filter_posts_search( $sql ) { return $sql . ' /* posts_search */'; }