Archived topic
Block Element Not Showing up on Search Results Page
21 replies · Started by Samuel on December 9, 2020
I have an element which displays a search bar just after the page header on several pages. I want it to also show on the search results page and I have search results selected as a location but it's not showing. I'm not sure what I'm missing?
This is a project in development for a client-login to the test site is provided below.
Hi there,
what happens if you set the Location to Entire Site ? Does it then appear?
I added "entire site" and it still didn't show on the search results page.
Hi,
I added “entire site” and it still didn’t show on the search results page.
Can you try disabling all child themes(use default GP only) & plugins except GP Premium and check if it still occurs?
Let us know.
I tried disabling all custom code and I found the code that is causing the problem but I cannot figure out why. I never would have imagined this was the issue.
On the site we modify the where clause on the search to customize how posts are searched. The code should be checking to only modify the main query on the page. Here's an excerpt of the code:
add_filter( 'posts_where', function( $where ) {
//Exit if this isn't a search.
if ( ! is_main_query() || ! is_search() || is_admin() ) {
return $where;
}
I'm don't know why this is preventing the GP hook from running but this is where the issue is happening. What needs to be changed so that the GP hook runs?
Hi there,
What hook are you using in the Element?
Is there anything more to that function?
I'm using the generate_after_header hook.
Here is the entire function:
/**
* Customize the search where.
*/
add_filter( 'posts_where', function( $where ) {
//Exit if this isn't a search.
if ( ! is_main_query() || ! is_search() || is_admin() ) {
return $where;
}
global $wpdb;
$search_post_types = '';
$i = 0;
foreach ( ett_get_search_post_types() as $post_type ) {
if ( $i > 0 ) { $search_post_types .= ','; }
$search_post_types .= "'" . esc_sql( $post_type ) . "'";
$i++;
}
$search_phrase = esc_sql( get_search_query( false ) );
$where = "
AND ID IN
(SELECT $wpdb->posts.ID
FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON $wpdb->term_relationships.object_id = $wpdb->posts.id
LEFT JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id AND $wpdb->term_taxonomy.taxonomy = 'ett_search_terms'
LEFT JOIN $wpdb->terms ON $wpdb->terms.term_id = $wpdb->term_taxonomy.term_id
WHERE ($wpdb->posts.post_title LIKE '%$search_phrase%' OR $wpdb->posts.post_content LIKE '%$search_phrase%' OR $wpdb->posts.post_excerpt LIKE '%$search_phrase%' OR $wpdb->terms.name = '$search_phrase')
AND ( $wpdb->posts.post_status = 'publish' AND $wpdb->posts.post_type IN ($search_post_types) )";
//filter by year where necessary
if ( $year = get_query_var( 'ett_search_year' ) ) {
$year = esc_sql( $year );
$where .= "
AND YEAR($wpdb->posts.post_date) = '$year'";
}
//filter by taxonomy where necessary.
if ( $tax = get_query_var( 'ett_search_tax') ) {
$tax = esc_sql( $tax );
$term = esc_sql( get_query_var( 'ett_search_term' ) );
$where .= "
AND $wpdb->posts.ID IN
( SELECT $wpdb->posts.ID
FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON $wpdb->term_relationships.object_id = $wpdb->posts.id
LEFT JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id AND $wpdb->term_taxonomy.taxonomy = '$tax'
LEFT JOIN $wpdb->terms ON $wpdb->terms.term_id = $wpdb->term_taxonomy.term_id
WHERE $wpdb->terms.term_id = '$term')";
}
//add order by and close parenthesis
$where .= "
ORDER BY $wpdb->terms.term_id DESC, $wpdb->posts.post_date)";
return $where;
}, 20, 2);
Hmm, it's possible that it's altering the query which is confusing the Display Rules.
You could try doing something like this to bypass them:
add_filter( 'generate_block_element_display', function( $display, $element_id ) {
if ( 123 === $element_id && is_search() ) {
$display = true;
}
return $display;
}, 10, 2 );
Just update 123 with the ID of the Block Element.
Let me know :)
That code didn't work unfortunately. The filter isn't being triggered unless I remove the where logic we apply to the search.
In that case, it must be messing with the is_search() conditional. You may need to find an alternative to that function, or have someone debug it so it doesn't affect the condition.
I just got back to debugging this. Here is the problem:
I have a filter on 'posts_where'. In order to target the primary query only I have the following check:
if ( ! is_main_query() || ! is_search() || is_admin() ) {
return $where;
}
I stepped through the code and the filter is run when GP searches for elements. And for some reason when that query is run is_main_query() returns 'true.' This seems wrong to me unless there is something I'm not grasping. I would not expect a query for GP elements to return true for is_main_query(). If this is correct, is there another way I could easily check to see if this query is a GP query for page elements?
That's strange, it definitely shouldn't be.
If you have access to the $post_type variable in the function, you can check to see if it's an Element:
if ( 'gp_elements' === $post_type ) {
return $where;
}
I tried to check $post_type using this code:
global $post_type;
if ( 'gp_elements' === $post_type ) {
return $where;
}
Oddly $post_type was still equal to the $post_types set in the main query.
Debugging through it I've found:
The main query is run.
Then the query is run for GP Elements.
When that query is run the global query var is still set to the main query which is why is_main_query() returns true on the query for elements.
The $post_type variable also remains set to the previous query (which is the main query) and contains the values set in the main query.
So, for some reason, the variables associated with the true main query are not being reset after the main query is run so the subsequent elements query cannot be easily filtered.
Right now I've done this but it is a real hack:
if ( strpos( $where, 'gp_elements' ) !== false ) {
return $where;
}
It works but obviously is ugly and fragile. I'm not sure if there is another solution though unless there is a bug to be fixed here somewhere on the WP or GP side. But I'm not sure.
Elements uses get_posts() to loop through the published Elements. I'm not sure something like wp_reset_query() would even work with get_posts(), but you could try it in elements/elements.php after the foreach.
Something interesting--the query for elements is run after the main query. I would if there needs to be some kind of reset after the main query?
I looked at the code, and I wouldn't think wp_reset_query() would do anything related to get_posts()?