Intercept Advanced Custom Fields (ACF) Relationship Field Searches
Advanced Custom Fields has the option of adding a search input to Relationship fields:
By default SearchWP will not intercept these searches, but using this snippet you can make that happen:
<?php | |
function my_searchwp_acf_relationship_field_search( $args, $field, $post_id ) { | |
if ( empty( $args['s'] ) || ! class_exists( 'SWP_Query' ) ) { | |
return $args; | |
} | |
// Assume that the SearchWP engine to use is the defined admin search engine | |
// from SearchWP's engine settings. | |
$admin_engine = \SearchWP\Settings::get_admin_engine(); | |
$engine_name = ! empty( $admin_engine ) ? $admin_engine : 'default'; | |
$engine = new \SearchWP\Engine( $engine_name ); | |
$engine_sources = $engine->get_sources(); | |
if ( empty( $engine_sources ) ) { | |
return array( 0 ); | |
} | |
// Get Source post types | |
$engine_sources = array_map( | |
function( $source ) { | |
$source_name = $source->get_name(); | |
$source_name_parts = explode( SEARCHWP_SEPARATOR, $source_name ); | |
return $source_name_parts[1] ?? false; | |
}, | |
$engine_sources | |
); | |
$engine_sources = array_filter( | |
$engine_sources, | |
function( $source ) { | |
return false !== strpos( $source, 'post' . SEARCHWP_SEPARATOR ); | |
}, | |
ARRAY_FILTER_USE_KEY | |
); | |
if ( empty( $engine_sources ) ) { | |
return array( 0 ); | |
} | |
$searchwp_args = array( | |
'engine' => $engine_name, // The SearchWP engine to use. | |
's' => $args['s'], // Pass along the search query. | |
'fields' => 'ids', // Return only post IDs. | |
); | |
if ( ! empty( $args['taxonomy' ] ) ) { | |
$tax_arg = explode( ':', $args['taxonomy'] ); | |
$searchwp_args['tax_query'] = array( | |
array( | |
'taxonomy' => $tax_arg[0], | |
'field' => 'slug', | |
'terms' => $tax_arg[1], | |
), | |
); | |
} | |
if ( ! empty( $args['post_type'] ) ) { | |
$searchwp_args['post_type'] = array_intersect( $args['post_type'], array_values( $engine_sources ) ); | |
} | |
// Tell SearchWP to NOT log this search. | |
add_filter( 'searchwp\statistics\log', '__return_false' ); | |
// Retrieve SearchWP results. | |
$results = new SWP_Query( $searchwp_args ); | |
// If there are no results, we need to force ACF to reflect that. | |
if ( empty( $results->posts ) ) { | |
$results->posts = array( 0 ); | |
} | |
// We're going to use SearchWP's results to handle the restrictions as outlined. | |
$args['s'] = ''; | |
$args['order'] = ''; | |
$args['orderby'] = 'post__in'; | |
$args['post__in'] = $results->posts; | |
return $args; | |
} | |
// Tell SearchWP to intercept all ACF Relationship field searches. | |
add_filter( 'acf/fields/relationship/query', 'my_searchwp_acf_relationship_field_search', 10, 3 ); | |
// Tell SearchWP to intercept a single ACF Relationship field search. | |
// add_filter( 'acf/fields/relationship/query/name=my_acf_relationship_field_name', 'my_searchwp_acf_relationship_field_search', 10, 3 ); |
There are a couple of things to note with this snippet:
You can control which Relationship field(s) utilizes SearchWP for searches. Line 85 uses ACF’s hook to apply SearchWP’s results to all Relationship field searches.
If instead you want to pick and choose which Relationship fields you’d like SearchWP to work with, comment out line 85 and uncomment line 88 making sure to update my_acf_relationship_field_name
with the name of one of your Relationship fields. You can repeat the hook (updating the Relationship field name) for each additional field as well.
The second thing to note is that the my_searchwp_acf_relationship_field_search
callback (which is what actually modifies the ACF search results for this use case) uses the SearchWP engine that you have defined as the Admin search engine on the Advanced tab of the SearchWP settings screen.
If you’d like to override that you can provide the SearchWP engine name to use on line 13 of the snippet.
Once this hook is in place SearchWP will intercept the applicable Advanced Custom Fields Relationship Field searches, returning results from SearchWP itself.