@@ -71,7 +71,7 @@ public function init() {
7171 ], 10 , 2 );
7272
7373 if ( is_admin () ) {
74- add_action ( 'pre_get_posts ' , [ $ this , 'search_custom_fields ' ] );
74+ add_action ( 'pre_get_posts ' , [ $ this , 'search_meta_or_title ' ] );
7575 add_action ( 'pre_get_posts ' , [ $ this , 'sort_by_meta ' ] );
7676 }
7777 }
@@ -201,18 +201,27 @@ public function column_content( $column_name, $post_id ) {
201201 *
202202 * @param \WP_Query $query WordPress query object.
203203 */
204- public function search_custom_fields ( \WP_Query $ query ) {
204+ public function search_meta_or_title ( \WP_Query $ query ) {
205205 global $ typenow ;
206206 $ searchterm = $ query ->query_vars ['s ' ];
207207
208- if ( ! $ query ->is_main_query () || $ typenow !== $ this ->post_type || empty ( $ searchterm ) ) {
208+ if (
209+ ! $ query ->is_main_query ()
210+ || $ typenow !== $ this ->post_type
211+ || empty ( $ searchterm )
212+ ) {
209213 return ;
210214 }
211215
212216 $ meta_columns = array_filter ( $ this ->columns , function ( $ column ) {
213217 return 'meta ' === $ column ['type ' ] && $ column ['searchable ' ];
214218 } );
215219
220+ // Bail out and use default search if no searchable meta columns are defined.
221+ if ( empty ( $ meta_columns ) ) {
222+ return ;
223+ }
224+
216225 $ meta_query = [ 'relation ' => 'OR ' ];
217226
218227 foreach ( $ meta_columns as $ key => $ column ) {
@@ -223,12 +232,47 @@ public function search_custom_fields( \WP_Query $query ) {
223232 ];
224233 }
225234
235+ $ query ->set ( 'meta_query ' , $ meta_query );
236+
226237 /**
227- * The search parameter needs to be removed from the query, because it will prevent
228- * the proper posts from being found.
238+ * Remove search parameter.
239+ *
240+ * The search parameter needs to be removed from the query, otherwise posts can’t be found.
241+ * A disadvantage of this is that all the logic in \WP_Query::parse_search() is lost.
242+ *
243+ * @see \WP_Query::parse_search()
229244 */
230245 $ query ->set ( 's ' , '' );
231246
232- $ query ->set ( 'meta_query ' , $ meta_query );
247+ // Fixes the "Search results for …" label in the post list table.
248+ add_filter ( 'get_search_query ' , function ( $ query ) use ( $ searchterm ) {
249+ return $ searchterm ;
250+ } );
251+
252+ /**
253+ * Update meta query to include search for title.
254+ *
255+ * This logic is taken from a StackOverflow answer:
256+ * @link https://wordpress.stackexchange.com/a/178492/22506
257+ */
258+ add_filter ( 'get_meta_sql ' , function ( $ sql ) use ( $ searchterm ) {
259+ global $ wpdb ;
260+
261+ // Run only once.
262+ static $ nr = 0 ;
263+
264+ if ( 0 != $ nr ++ ) {
265+ return $ sql ;
266+ }
267+
268+ // Modify the WHERE part.
269+ $ sql ['where ' ] = sprintf (
270+ " AND ( %s OR %s ) " ,
271+ $ wpdb ->prepare ( "{$ wpdb ->posts }.post_title like '%%%s%%' " , $ searchterm ),
272+ mb_substr ( $ sql ['where ' ], 5 , mb_strlen ( $ sql ['where ' ] ) )
273+ );
274+
275+ return $ sql ;
276+ } );
233277 }
234278}
0 commit comments