|

SearchWP for BuddyBoss

Upload and activate Search WP

Enable a Supplemental Engine

Add Buddypress and bbPress extensions

Add custom code to enable BuddyPress activity entries

get the source here: https://gist.github.com/jchristopher/7f5d249fddaa6c09d5792879529398c2

<?php

/**
 * Custom SearchWP Source for BuddyPress Activity.
 * NOTE: Requires SearchWP 4
 */
add_action( 'plugins_loaded', function() {
	// if ( ! class_exists( '\SearchWP\Source' ) || ! function_exists( 'bp_activity_get' ) ) {
	// 	return;
	// }

	class BuddyPressActivity extends \SearchWP\Source {

		protected $name         = 'buddypressactivity';
		protected $db_id_column = 'id';

		function __construct() {
			global $wpdb;

			$this->db_table = $wpdb->base_prefix . 'bp_activity';

			$this->labels = [
				'plural'   => 'BuddyPress Activity',
				'singular' => 'BuddyPress Activity',
			];

			$this->attributes = [ [
				'name'    => 'content',
				'label'   => 'Content',
				'default' => \SearchWP\Utils::get_min_engine_weight(),
				'data'    => function( $entry_id ) {
					$content = '';
					$entry   = bp_activity_get( [ 'in' => [ $entry_id ] ] );

					if ( ! empty( $entry['activities'] ) ) {
						$content = $entry['activities'][0]->content;
					}

					return $content;
				},
			], ];
		}

		// Restrict to Activity updates.
		protected function db_where() {
			return [ [
				'column' => 'component',
				'value'  => 'activity',
			] ];
		}

		// Return results of bp_activity_get() for this Activity entry.
		public function entry( \SearchWP\Entry $entry, $query = false ) {
			return bp_activity_get( [ 'in' => [ $entry->get_id() ] ] );
		}
	}

	add_filter( 'searchwp\sources', function( $sources ) {
		$sources[] = new BuddyPressActivity();

		return $sources;
	} );
} );

Add custom code to enable BuddyPress XProfile Fields as a source

<?php

use SearchWP\Entry;
use SearchWP\Source;
use SearchWP\Utils;
use SearchWP\Option;
use SearchWP\Settings;

function dlog($message, $shouldNotDie = true)
{
		error_log(print_r($message, true));
}

add_action( 'plugins_loaded', function() {
	// if ( ! class_exists( '\SearchWP\Source' ) || ! function_exists( 'bp_activity_get' ) ) {
	// 	return;
	// }
	
	class BuddyPressUserXprofile extends \SearchWP\Source {

		protected $name         = 'buddybossuserxprofile';
		protected $db_id_column = 'id';

		function __construct() {
			
					global $wpdb;

			$this->db_table = $wpdb->base_prefix . 'users';
					
			$bp_fields_table = $wpdb->prefix . 'bp_xprofile_fields';
			$delimiter = '_';
			
			//write_log($bp_fields_table);
							
			$this->labels = [
			'plural'   => 'BuddyPress Users',
			'singular' => 'BuddyPress User',
			];
					
			$fields = $wpdb->get_results("SELECT * FROM {$bp_fields_table}");

			//write_log($fields);

			$attributes = array();

			foreach ( $fields as $field ) {

				//generate slug for searchwp
				$bp_user_attribute_slug = strtolower(trim(preg_replace('/[\s-]+/', $delimiter, preg_replace('/[^A-Za-z0-9-]+/', $delimiter, preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $field->name))))), $delimiter));
				
				$bp_user_attribute_name = $field->name;
				
				//write_log($bp_user_attribute_name);
						
						$attributes[] = [
				'name'    => $bp_user_attribute_slug,
				'label'   => $bp_user_attribute_name,
				'default' => \SearchWP\Utils::get_min_engine_weight(),
				'data'    => function( $user_id ) use ($bp_user_attribute_name) {				
								
									//$field_id = xprofile_get_field_id_from_name($bp_user_attribute_slug);
									//return xprofile_get_field_data($bp_user_attribute_slug, $user_id);
									
									return bp_get_member_profile_data(
										array( 
											'field'=>$bp_user_attribute_name,
											'user_id' => $user_id 
										)
									);
				},
			];
					}
					
			$this->attributes = $attributes;
		}

		public function entry( \SearchWP\Entry $entry, $query = false ) {
			$user = get_user_by( 'id', $entry->get_id() );          
			return $user;
		}
	}

	add_filter( 'searchwp\sources', function( $sources ) {
		$sources[] = new BuddyPressUserXprofile();
		//write_log(count($sources));
		return $sources;
		
		//[09-Sep-2022 03:28:11 UTC] WordPress database error Table 'askoneguidestg_1657318144.wp_2_users' doesn't exist for query SELECT SQL_CALC_FOUND_ROWS wp_2_users.id FROM wp_2_users WHERE 1=1 LIMIT 1  made by do_action('wp_ajax_searchwp_index_stats'), WP_Hook->do_action, WP_Hook->apply_filters, SearchWP\Index\Controller->_index_stats, SearchWP\Index\Controller->get_stats, SearchWP\Index\Controller->get_count_entries, SearchWP\Source->get_entry_db_records
	} );
	if(function_exists('bbp_get_user_profile_url')){
		add_filter( 'author_link', function( $link, $author_id, $author_nicename){
		
			$link = bbp_get_user_profile_url($author_id);
			return $link;
			
		},10,3);  
		}
} );



if (!function_exists('write_log')) {

	function write_log($log) {
			if (true === WP_DEBUG) {
					if (is_array($log) || is_object($log)) {
							error_log(print_r($log, true));
					} else {
							error_log($log);
					}
			}
	}

}

Configure searchwp sources for the supplemental engine

Create Search template and add to your child theme

<?php

/* Template Name: SearchWP Results */

global $post;

// Retrieve applicable query parameters.
$search_query = isset( $_GET['searchwp'] ) ? sanitize_text_field( $_GET['searchwp'] ) : null;
$search_page  = isset( $_GET['swppg'] ) ? absint( $_GET['swppg'] ) : 1;

// Perform the search.
$search_results    = [];
$search_pagination = '';
if ( ! empty( $search_query ) && class_exists( '\\SearchWP\\Query' ) ) {
	$searchwp_query = new \SearchWP\Query( $search_query, [
		'engine' => 'supplemental', // The Engine name.
		'fields' => 'all',          // Load proper native objects of each result.
		'page'   => $search_page,
	] );

	$search_results = $searchwp_query->get_results();

	$search_pagination = paginate_links( array(
		'format'  => '?swppg=%#%',
		'current' => $search_page,
		'total'   => $searchwp_query->max_num_pages,
	) );
}

get_header(); ?>

<div id="primary" class="content-area">
	<main id="main" class="site-main" role="main">

		<header class="page-header">
			<h1 class="page-title">
				<?php if ( ! empty( $search_query ) ) : ?>
					<?php printf( __( 'Search Results for: %s' ), esc_html( $search_query ) ); ?>
				<?php else : ?>
					SearchWP Supplemental Search
				<?php endif; ?>
			</h1>

			<!-- BEGIN Supplemental Engine Search form -->
			<form role="search" method="get" class="search-form"
			action="<?php echo site_url( 'search-results/' ); ?>">
				<label>
					<span class="screen-reader-text">
					<?php echo _x( 'Search for:', 'label' ) ?>
					</span>
					<input type="search" class="search-field"
					name="searchwp"
					placeholder="<?php echo esc_attr_x( 'Search...', 'placeholder' ) ?>"
					value="<?php echo isset( $_GET['searchwp'] ) ? esc_attr( $_GET['searchwp'] ) : '' ?>"
					title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" />
				</label>
				<input type="submit" class="search-submit"
					value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" />
			</form>
			<!-- END Supplemental Engine Search form -->
		</header>

		<?php if ( ! empty( $search_query ) && ! empty( $search_results ) ) : ?>
			<?php  foreach ( $search_results as $search_result ) : ?>
				<article class="page hentry search-result">
					<?php
					switch( get_class( $search_result ) ) {
					case 'WP_Post':
						$post = $search_result;
						?>
						<div class="entry-wrap">
						<div class="entry-thumb-col">
						<a href="<?php echo get_permalink(); ?>">
						    
						 <?php if ( has_post_thumbnail() ) {
                            the_post_thumbnail('thumbnail');} 
                            if ( !has_post_thumbnail() ) {
                            $entry_image_id = intval(get_post_meta( get_the_ID(), 'expert-profile-image', true));
						if ($entry_image_id) {
						    $entry_image = wp_get_attachment_image_src($entry_image_id, 'medium');
						    if ($entry_image) {
						        ?><img width="150" height="150" src="<?php echo $entry_image[0]; ?>" /><?php 
						        
						    }
						    } 
						if ( $entry_image_id==0 ) {
						    ?>
						    
						    <img width="150" height="150" src="<?php echo bp_search_get_post_thumbnail_default( get_post_type($search_result->data->ID) ) ?>" />
						    <?php }} ?>
						</a></div>
						<div class="entry-content-col">
						<header class="entry-header"><h2 class="entry-title">
							<a href="<?php echo get_permalink(); ?>"><?php the_title(); ?></a>
						</h2></header>
						<div class="entry-summary"><a href="<?php echo get_permalink(); ?>"><?php the_excerpt(); ?><?php echo get_post_meta(get_the_ID(), 'expert-bio', true); ?></a></div>
						</div></div>
						<?php
						wp_reset_postdata();
						break;
					case 'WP_User':
						?>
						<div class="entry-wrap">
						<div class="entry-thumb-col">
						<a href="<?php echo bbp_get_user_profile_url( $search_result->data->ID ); ?>">
						<?php echo get_avatar( $search_result->data->ID, 150 ); ?>
						</a></div>
    
						<div class="entry-content-col">
						<header class="entry-header"><h2 class="entry-title">
							<a href="<?php echo bbp_get_user_profile_url( $search_result->data->ID ); ?>">
								<?php echo esc_html( $search_result->data->display_name ); ?>
							</a>
						</h2></header>
						<div class="entry-summary">
						    <div class="member-custom-field-directory">
										<?php $xprofile_company = xprofile_get_field_data( 'Company Name', $search_result->data->ID ); 
										    echo xprofile_get_field_data( 'Title', $search_result->data->ID ) ;
    										if ($xprofile_company) {
    										    echo " at ".$xprofile_company;
    										}
										?> 
									</div>	
							<?php echo wp_kses_post( get_the_author_meta( 'description',
											$search_result->data->ID ) ); ?>
						</div></div></div>
						<?php
						break;
					}
					?>
				</article>
			<?php endforeach; ?>

			<?php if ( $searchwp_query->max_num_pages > 1 ) : ?>
				<div class="navigation pagination" role="navigation">
					<h2 class="screen-reader-text">Results navigation</h2>
					<div class="nav-links"><?php echo wp_kses_post( $search_pagination ); ?></div>
				</div>
			<?php endif; ?>
		<?php elseif ( ! empty( $search_query ) ) : ?>
			<p>No results found, please search again.</p>
		<?php endif; ?>

	</main> <!-- .site-main -->
</div> <!-- .content-area -->

<?php get_footer(); ?>

Now lets style the search results

.entry-thumb-col {
    width: 20%;
    float: left;
    height: 100%;
    text-align: center;
}

.entry-content-col {
    width: 80%;
    float: left;
    /*padding: 10px;*/
}

.entry-wrap:after {
  content: "";
  display: table;
  clear: both;
  background-color: #fff;
}

.entry-wrap {
  margin: 30px;
  background-color: #fff;
  box-shadow: 0px 0px 10px 0px rgb(0 0 0 / 15%);
  transition: background 0.3s, border 0.3s, border-radius 0.3s, box-shadow 0.3s;
  padding: 20px;
	padding-left: 0;
  border-radius: 5px;
}

.entry-thumb-col img {
    border-radius: 100px;
}

.entry-title a{
    font-size: 24px;
    font-weight: bold;
    text-align: left;
    color: #000;
}
.entry-summary a {
    color: #000;
}

.entry-header {
    margin-bottom: 1rem;
}

.entry-summary p:last-child {
    margin-bottom: 0px;
}

Create your Search Results page and use your new Search Results template

Create a shortcode for your search form. We want the search form action to point to the search page that we created for the search template. (/search-results/)

function SocialHost_display_search_form() {
	$search_form = '<form method="get" id="search-form" action="'. esc_url(site_url( '/search-results/' )) .'">
		<input type="search" name="searchwp" id="searchwp" placeholder="Search..">
  		<button type="submit" title="Search" aria-label="Search">
			<i aria-hidden="true" class="fas fa-search"></i>
		</button>
	</form>';
	return $search_form;
}
add_shortcode('display_search_form', 'SocialHost_display_search_form');

Add the shortcode to a header [display_search_form]

Style the search form. Here is an example that uses a couple of Elementor global variables

#search-form button {
    
    background-color: var( --e-global-color-primary );
    --e-search-form-submit-icon-size: 18px;
    margin-left: -5px;
    border-radius: 0px 5px 5px 0px !important;
}

#search-form input {
    background-color: var( --e-global-color-4e98020 );
    margin-right:  0px;
    border-radius: 5px 0px 0px 5px !important;
    width: 70%;
}

#search-form  {
    margin-bottom: 0px;
}