/** * Returns a trimmed reply content string. * Works for replies as well as topics. * Must be used while inside the loop */ function buddyboss_global_search_reply_intro($character_limit = 50) { $content = ''; switch (get_post_type(get_the_ID())) { case 'topic': $reply_content = bbp_get_topic_content(get_the_ID()); break; case 'reply': $reply_content = bbp_get_reply_content(get_the_ID()); break; default: $reply_content = get_the_content(); break; } if ($reply_content) { $content = wp_strip_all_tags($reply_content, true); $search_term = buddyboss_global_search()->search->get_search_term(); $search_term_position = strpos($content, $search_term); if ($search_term_position !== false) { $shortened_content = '...' . substr($content, $search_term_position, $character_limit); //highlight search keyword $shortened_content = str_replace($search_term, "<strong>" . $search_term . "</strong>", $shortened_content); } else { $shortened_content = substr($content, 0, $character_limit); } if (strlen($content) > $character_limit) { $shortened_content .= '...'; } $content = $shortened_content; } return apply_filters('buddyboss_global_search_reply_intro', $content); }
/** * Load search helpers for each searchable acf group. * * @param array $helpers * @return array * @since 1.0.0 */ function bboss_global_search_helpers_acf($helpers) { /** * Check which acfs we need to search. * And create one helper class object for each. */ $searchable_types = buddyboss_global_search()->option('items-to-search'); foreach ($searchable_types as $searchable_type) { //if name starts with acf- $pos = strpos($searchable_type, 'acf-'); if ($pos === 0) { $acf_field_group = str_replace('acf-', '', $searchable_type); require_once BUDDYBOSS_GLOBAL_SEARCH_PLUGIN_DIR . 'includes/plugins/search-acf/class.BBoss_Global_Search_ACF.php'; $helpers[$searchable_type] = new BBoss_Global_Search_ACF($acf_field_group); } } return $helpers; }
function invite_anyone_add_js() { global $bp; if ($bp->current_action == BP_INVITE_ANYONE_SLUG || isset($bp->action_variables[1]) && $bp->action_variables[1] == BP_INVITE_ANYONE_SLUG) { wp_dequeue_script('invite-anyone-autocomplete-js'); wp_dequeue_script('invite-anyone-js'); $min = '-min'; if (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) { $min = ''; } wp_enqueue_script('invite-anyone-autocomplete-js', buddyboss_global_search()->assets_url . "/js/invite-anyone/jquery.autocomplete{$min}.js", array('jquery')); wp_register_script('invite-anyone-js', buddyboss_global_search()->assets_url . '/js/invite-anyone/group-invites-js.js', array('invite-anyone-autocomplete-js')); wp_enqueue_script('invite-anyone-js'); // Add words that we need to use in JS to the end of the page // so they can be translated and still used. $params = apply_filters('ia_get_js_strings', array('unsent_invites' => __('Click “Send Invites” to finish sending your new invitations.', 'invite-anyone'))); wp_localize_script('invite-anyone-js', 'IA_js_strings', $params); } }
/** * Load search helpers for each searchable custom post type. * * @param array $helpers * @return array * @since 1.0.0 */ function bboss_global_search_helpers_cpts($helpers) { /** * Check which cpts we need to search. * And create one helper class object for each. */ $searchable_types = buddyboss_global_search()->option('items-to-search'); foreach ($searchable_types as $searchable_type) { //if name starts with cpt- $pos = strpos($searchable_type, 'cpt-'); if ($pos === 0) { $cpt_name = str_replace('cpt-', '', $searchable_type); $cpt_obj = get_post_type_object($cpt_name); //is cpt still valid? if ($cpt_obj && !is_wp_error($cpt_obj)) { require_once BUDDYBOSS_GLOBAL_SEARCH_PLUGIN_DIR . 'includes/plugins/search-cpt/class.BBoss_Global_Search_CPT.php'; $helpers[$searchable_type] = new BBoss_Global_Search_CPT($cpt_name, $searchable_type); } } } return $helpers; }
/** * Generates sql for members search. * * @todo: if Mr.X has set privacy of xprofile field 'location' data as 'private' * then, location of Mr.X shouldn't be checked in searched. * * @since 1.0.0 * @param string $search_term * @param boolean $only_totalrow_count * * @return string sql query */ public function sql($search_term, $only_totalrow_count = false) { global $wpdb, $bp; $query_placeholder = array(); $items_to_search = buddyboss_global_search()->option('items-to-search'); $COLUMNS = " SELECT "; if ($only_totalrow_count) { $COLUMNS .= " COUNT( DISTINCT u.id ) "; } else { $COLUMNS .= " DISTINCT u.id, 'members' as type, u.display_name LIKE '%%%s%%' AS relevance, a.date_recorded as entry_date "; $query_placeholder[] = $search_term; } $FROM = " {$wpdb->users} u JOIN {$bp->members->table_name_last_activity} a ON a.user_id=u.id "; $WHERE = array(); $WHERE[] = "1=1"; $where_fields = array(); /* ++++++++++++++++++++++++++++++++ * wp_users table fields +++++++++++++++++++++++++++++++ */ $user_fields = array(); foreach ($items_to_search as $item) { //should start with member_field_ prefix //see print_search_options if (strpos($item, 'member_field_') === 0) { $user_fields[] = str_replace('member_field_', '', $item); } } if (!empty($user_fields)) { $conditions_wp_user_table = array(); foreach ($user_fields as $user_field) { $conditions_wp_user_table[] = $user_field . " LIKE '%%%s%%' "; $query_placeholder[] = $search_term; } $clause_wp_user_table = "u.id IN ( SELECT ID FROM {$wpdb->users} WHERE ( "; $clause_wp_user_table .= implode(' OR ', $conditions_wp_user_table); $clause_wp_user_table .= " ) ) "; $where_fields[] = $clause_wp_user_table; } /* _____________________________ */ /* ++++++++++++++++++++++++++++++++ * xprofile fields +++++++++++++++++++++++++++++++ */ //get all selected xprofile fields if (function_exists('bp_is_active') && bp_is_active('xprofile')) { $groups = bp_xprofile_get_groups(array('fetch_fields' => true)); if (!empty($groups)) { $selected_xprofile_fields = array(); foreach ($groups as $group) { if (!empty($group->fields)) { foreach ($group->fields as $field) { $item = 'xprofile_field_' . $field->id; if (!empty($items_to_search) && in_array($item, $items_to_search)) { $selected_xprofile_fields[] = $field->id; } } } } if (!empty($selected_xprofile_fields)) { //u.id IN ( SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE '%%%s%%' ) $clause_xprofile_table = "u.id IN ( SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE '%%%s%%' AND field_id IN ( "; $clause_xprofile_table .= implode(',', $selected_xprofile_fields); $clause_xprofile_table .= " ) ) "; $where_fields[] = $clause_xprofile_table; $query_placeholder[] = $search_term; } } } /* _____________________________ */ if (!empty($where_fields)) { $WHERE[] = implode(' OR ', $where_fields); } // other conditions $WHERE[] = " a.component = 'members' "; $WHERE[] = " a.type = 'last_activity' "; $sql = $COLUMNS . ' FROM ' . $FROM . ' WHERE ' . implode(' AND ', $WHERE); if (!$only_totalrow_count) { $sql .= " GROUP BY u.id "; } return $wpdb->prepare($sql, $query_placeholder); }
/** * Perform search and generate search results * @param mixed $args * @since 1.0.0 */ public function do_search($args = '') { global $wpdb; $defaults = array('search_term' => '', 'search_subset' => 'all', 'searchable_items' => buddyboss_global_search()->option('items-to-search'), 'per_page' => 10, 'current_page' => 1, 'count_total' => true, 'template_type' => ''); $args = wp_parse_args($args, $defaults); $this->search_args = $args; //save it for using in other methods //bail out if nothing to search for if (!$args['search_term']) { return; } if ('all' == $args['search_subset']) { /** * 1. Generate a 'UNION' sql query for all searchable items with only ID, RANK, TYPE(posts|members|..) as columns, order by RANK DESC. * 3. Generate html for each of them */ /* an example UNION query :- ----------------------------------------------------- ( SELECT wp_posts.id , 'posts' as type, wp_posts.post_title LIKE '%ho%' AS relevance, wp_posts.post_date as entry_date FROM wp_posts WHERE 1=1 AND ( ( (wp_posts.post_title LIKE '%ho%') OR (wp_posts.post_content LIKE '%ho%') ) ) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND ( wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private' ) ) UNION ( SELECT DISTINCT g.id, 'groups' as type, g.name LIKE '%ho%' AS relevance, gm2.meta_value as entry_date FROM wp_bp_groups_groupmeta gm1, wp_bp_groups_groupmeta gm2, wp_bp_groups g WHERE 1=1 AND g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND ( g.name LIKE '%ho%' OR g.description LIKE '%ho%' ) ) ORDER BY relevance DESC, entry_date DESC LIMIT 0, 10 ---------------------------------------------------- */ $sql_queries = array(); foreach ($args['searchable_items'] as $search_type) { if (!isset($this->search_helpers[$search_type])) { continue; } /** * the following variable will be an object of current search type helper class * e.g: an object of BBoss_Global_Search_Groups or BBoss_Global_Search_Posts etc. * so we can safely call the public methods defined in those classes. * This also means that all such classes must have a common set of methods. */ $obj = $this->search_helpers[$search_type]; $sql_queries[] = "( " . $obj->union_sql($args['search_term']) . " ) "; } if (empty($sql_queries)) { //thigs will get messy if program reaches here!! return; } $pre_search_query = implode(' UNION ', $sql_queries) . " ORDER BY relevance DESC, entry_date DESC "; if ($args['per_page'] > 0) { $offset = $args['current_page'] * $args['per_page'] - $args['per_page']; $pre_search_query .= " LIMIT {$offset}, {$args['per_page']} "; } $results = $wpdb->get_results($pre_search_query); /* $results will have a structure like below */ /* id | type | relevance | entry_date 45 | groups | 1 | 2014-10-28 17:05:18 40 | posts | 1 | 2014-10-26 13:52:06 4 | groups | 0 | 2014-10-21 15:15:36 */ if (!empty($results)) { $this->search_results['all'] = array('total_match_count' => 0, 'items' => array(), 'items_title' => array()); //segregate items of a type together and pass it to corresponsing search handler, so that an aggregate query can be done //e.g one single wordpress loop can be done for all posts foreach ($results as $item) { $obj = $this->search_helpers[$item->type]; $obj->add_search_item($item->id); } //now get html for each item foreach ($results as $item) { $obj = $this->search_helpers[$item->type]; $result = array('id' => $item->id, 'type' => $item->type, 'html' => $obj->get_html($item->id, $args['template_type']), 'title' => $obj->get_title($item->id)); $this->search_results['all']['items'][$item->id] = $result; } //now we've html saved for search results if (!empty($this->search_results['all']['items']) && $args['template_type'] != 'ajax') { /* ++++++++++++++++++++++++++++++++++ group items of same type together ++++++++++++++++++++++++++++++++++ */ //create another copy, of items, this time, items of same type grouped together $ordered_items_group = array(); foreach ($this->search_results['all']['items'] as $item_id => $item) { $type = $item['type']; if (!isset($ordered_items_group[$type])) { $ordered_items_group[$type] = array(); } $ordered_items_group[$type][$item_id] = $item; } foreach ($ordered_items_group as $type => &$items) { //now prepend html (opening tags) to first item of each type $first_item = reset($items); $start_html = "<div class='results-group results-group-{$type}'>" . "<h2 class='results-group-title'><span>" . apply_filters('bboss_global_search_label_search_type', $type) . "</span></h2>" . "<ul id='{$type}-stream' class='item-list {$type}-list'>"; $group_start_html = apply_filters("bboss_global_search_results_group_start_html", $start_html, $type); $first_item['html'] = $group_start_html . $first_item['html']; $items[$first_item['id']] = $first_item; //and append html (closing tags) to last item of each type $last_item = end($items); $end_html = "</ul></div>"; $group_end_html = apply_filters("bboss_global_search_results_group_end_html", $end_html, $type); $last_item['html'] = $last_item['html'] . $group_end_html; $items[$last_item['id']] = $last_item; } //replace orginal items with this new, grouped set of items $this->search_results['all']['items'] = array(); foreach ($ordered_items_group as $type => $grouped_items) { foreach ($grouped_items as $item_id => $item) { $this->search_results['all']['items'][$item_id] = $item; } } /* ________________________________ */ } } } else { //if subset not in searchable items, bail out. if (!in_array($args['search_subset'], $args['searchable_items'])) { return; } if (!isset($this->search_helpers[$args['search_subset']])) { return; } /** * 1. Search top top 20( $args['per_page'] ) item( posts|members|..) * 2. Generate html for each of them */ $obj = $this->search_helpers[$args['search_subset']]; $pre_search_query = $obj->union_sql($args['search_term']) . " ORDER BY relevance DESC, entry_date DESC "; if ($args['per_page'] > 0) { $offset = $args['current_page'] * $args['per_page'] - $args['per_page']; $pre_search_query .= " LIMIT {$offset}, {$args['per_page']} "; } $results = $wpdb->get_results($pre_search_query); /* $results will have a structure like below */ /* id | type | relevance | entry_date 45 | groups | 1 | 2014-10-28 17:05:18 40 | posts | 1 | 2014-10-26 13:52:06 4 | groups | 0 | 2014-10-21 15:15:36 */ if (!empty($results)) { $obj = $this->search_helpers[$args['search_subset']]; $this->search_results[$args['search_subset']] = array('total_match_count' => 0, 'items' => array()); //segregate items of a type together and pass it to corresponsing search handler, so that an aggregate query can be done //e.g one single wordpress loop can be done for all posts foreach ($results as $item) { $obj->add_search_item($item->id); } //now get html for each item foreach ($results as $item) { $html = $obj->get_html($item->id, $args['template_type']); $result = array('id' => $item->id, 'type' => $args['search_subset'], 'html' => $obj->get_html($item->id, $args['template_type']), 'title' => $obj->get_title($item->id)); $this->search_results[$args['search_subset']]['items'][$item->id] = $result; } //now prepend html (opening tags) to first item of each type $first_item = reset($this->search_results[$args['search_subset']]['items']); $start_html = "<div class='results-group results-group-{$args['search_subset']}'>" . "<ul id='{$args['search_subset']}-stream' class='item-list {$args['search_subset']}-list'>"; $group_start_html = apply_filters("bboss_global_search_results_group_start_html", $start_html, $args['search_subset']); $first_item['html'] = $group_start_html . $first_item['html']; $this->search_results[$args['search_subset']]['items'][$first_item['id']] = $first_item; //and append html (closing tags) to last item of each type $last_item = end($this->search_results[$args['search_subset']]['items']); $end_html = "</ul></div>"; $group_end_html = apply_filters("bboss_global_search_results_group_end_html", $end_html, $args['search_subset']); $last_item['html'] = $last_item['html'] . $group_end_html; $this->search_results[$args['search_subset']]['items'][$last_item['id']] = $last_item; } } //html for search results is generated. //now, lets calculate the total number of search results, for all different types if ($args['count_total']) { $all_items_count = 0; foreach ($args['searchable_items'] as $search_type) { if (!isset($this->search_helpers[$search_type])) { continue; } $obj = $this->search_helpers[$search_type]; $total_match_count = $obj->get_total_match_count($this->search_args['search_term']); $this->search_results[$search_type]['total_match_count'] = $total_match_count; $all_items_count += $total_match_count; } $this->search_results['all']['total_match_count'] = $all_items_count; } }
/** * Get option * * @since BuddyPress Global Search (1.0.0) * * @param string $key Option key * * @uses BuddyBoss_Global_Search_Plugin::option() Get option * * @return mixed Option value */ public function option($key) { $value = buddyboss_global_search()->option($key); return $value; }
function buddyboss_global_search_results() { buddyboss_global_search()->search->print_results(); }