Posted on

Flatsome

Posts and pages on the product search results

The Flatsome theme, when combined with WooCommerce, has a product search results page that can also show posts and pages. That doesn’t work with Relevanssi out of the box, but fortunately can be made to work. The function that adds the functionality is hooked in place, so it’s easy to unhook the default function and replace it with something Relevanssi-friendly.

Like this:

remove_action( 'woocommerce_after_main_content', 'flatsome_pages_in_search_results', 10 );
// Add Pages and blog posts to top of search results if set.
function relevanssi_pages_in_search_results() {
	if ( ! is_search() || ! get_theme_mod( 'search_result', 1 ) ) {
		return;
	}
	global $post;
	if ( get_search_query() ) {
		$args = array(
			'post_type'  => 'post',
			's'          => get_search_query(),
            'relevanssi' => true,
		);
		$query = new WP_Query( $args );
		$posts = array();
		while ( $query->have_posts() ) {
			$query->the_post();
			array_push( $posts, $post->ID );
		}
		$args = array(
			'post_type'  => 'page',
			's'          => get_search_query(),
            'relevanssi' => true,
		);
		$query = new WP_Query( $args );
		$pages = array();
		while ( $query->have_posts() ) {
			$query->the_post();
			$wc_page = false;
			if ( 'page' === $post->post_type ) {
				foreach ( array( 'shop', 'cart', 'checkout', 'view_order', 'terms' ) as $wc_page_type ) {
					if ( $post->ID === wc_get_page_id( $wc_page_type ) ) {
						$wc_page = true;
					}
				}
			}
			if ( ! $wc_page ) {
				array_push( $pages, $post->ID );
			}
		}
		do_action( 'flatsome_products_page_loader' );
		if ( ! empty( $posts ) || ! empty( $pages ) ) {
			$list_type = get_theme_mod( 'search_result_style', 'slider' );
			if ( ! empty( $posts ) ) {
				echo '<hr><h4 class="uppercase">' . __( 'Posts found', 'flatsome' ) . '</h4>
' . do_shortcode( '[blog_posts columns="3" columns__md="3" columns__sm="2" type="' . $list_type . '" image_height="16-9" ids="' . implode( ',', $posts ) . '"]' );
			}
			if ( ! empty( $pages ) ) {
				echo '<hr><h4 class="uppercase">' . __( 'Pages found', 'flatsome' ) . '</h4>
' . do_shortcode( '[ux_pages columns="3" columns__md="3" columns__sm="2" type="' . $list_type . '" image_height="16-9" ids="' . implode( ',', $pages ) . '"]' );
			}
		}
	}
}
add_action( 'woocommerce_after_main_content', 'relevanssi_pages_in_search_results', 10 );

Add this to your Flatsome child theme functions.php, and the search results will show Relevanssi-generated results for posts and pages.

If the live search does not work

Flatsome has a built-in live search that should work with Relevanssi without modifications, but in case it doesn’t (for example searching for partial SKUs doesn’t work correctly even though it works in the Relevanssi admin search), you can add this to your child theme functions.php:

/**
 * Replaces the Flatsome live search default function (get_posts()) with Relevanssi.
 *
 * @param string $query    The search query, not used.
 * @param array  $args     The search query arguments.
 * @param array  $defaults The default values, not used.
 *
 * @return array An array of post objects.
 */
function rlv_flatsome_search_function( $query, $args, $defaults ) {
  $args['relevanssi'] = true;
  return get_posts( $args );
}

add_filter( 'flatsome_ajax_search_function', function() { return 'rlv_flatsome_search_function'; } );

Improving live search with product variations

If you want the live search to take the searcher directly to the right variation, here’s what you can do. First, make sure “Search Product SKU” setting in Flatsome is disabled. Then set Relevanssi to only index the products, not product variations, but make Relevanssi index variation SKUs for the main product.

Then we need to modify the Flatsome Ajax Seacrh function above like this:

function rlv_flatsome_search_function( $query, $args, $defaults ) {
  global $flatsome_live_search_query;
  $flatsome_live_search_query = $args['s'];
  $args['relevanssi'] = true;
  return get_posts( $args );
}

This stores the search query in a global variable so that we can use it later elsewhere. Then we need a filter function to adjust the permalinks so that when the search query matches a variation SKU, the product permalink is replaced with the variation permalink:

add_filter( 'post_type_link', 'rlv_wc_variation_permalink', 10, 2 );
function rlv_wc_variation_permalink( $permalink, $post ) {
  global $flatsome_live_search_query, $wp_query;
  if ( empty( $flatsome_live_search_query ) && isset( $wp_query->query_vars['s'] ) ) {
    $flatsome_live_search_query = $wp_query->query_vars['s'];
  }
  if ( 'product' === $post->post_type && ! empty( $flatsome_live_search_query ) ) {
    $variations = rlv_get_variation_ids( $post->ID );
    if ( isset( $variations[ $flatsome_live_search_query ] ) ) {
      remove_filter( 'post_type_link', 'rlv_wc_variation_permalink', 10 );
      return get_permalink( $variations[ $flatsome_live_search_query ] );
    }
  }
  return $permalink;
}

function rlv_get_variation_ids( $product_id ) {
  $variation_ids = array();
  $args = array(
    'post_parent'    => $product_id,
    'post_type'      => 'product_variation',
    'posts_per_page' => -1
  );
  $variations = get_posts( $args );
  if ( ! empty( $variations ) ) {
    foreach ( $variations as $variation ) {
      $variation_ids[ strtolower( get_post_meta( $variation->ID, '_sku', true ) ) ] = $variation->ID;
    }
  }
  return $variation_ids;
}

With these functions in place, the Flatsome live search will now open the product page with the correction variation selected if someone searches with the variation SKU.

Leave a Reply

Are you a Relevanssi Premium customer looking for support? Please use the Premium support form.

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.