<?php $query = elgg_extract('query', $vars, ''); $count = elgg_extract('count', $vars); $highlight_query = elgg_extract('highlight_query', $vars, true); // highlight search terms if (!empty($query)) { if ($highlight_query) { $searched_words = search_remove_ignored_words($query, 'array'); $query = search_highlight_words($searched_words, $query); } $query = "\"{$query}\""; } echo elgg_echo('search_advanced:results:title', [$count, $query]);
/** * Return a string with highlighted matched queries and relevant context * Determins context based upon occurance and distance of words with each other. * * @param string $haystack * @param string $query * @param int $min_match_context = 30 * @param int $max_length = 300 * @return string */ function search_get_highlighted_relevant_substrings($haystack, $query, $min_match_context = 30, $max_length = 300) { global $CONFIG; $haystack = strip_tags($haystack); $haystack_length = elgg_strlen($haystack); $haystack_lc = elgg_strtolower($haystack); $words = search_remove_ignored_words($query, 'array'); // if haystack < $max_length return the entire haystack w/formatting immediately if ($haystack_length <= $max_length) { $return = search_highlight_words($words, $haystack); return $return; } // get the starting positions and lengths for all matching words $starts = array(); $lengths = array(); foreach ($words as $word) { $word = elgg_strtolower($word); $count = elgg_substr_count($haystack_lc, $word); $word_len = elgg_strlen($word); // find the start positions for the words if ($count > 1) { $offset = 0; while (FALSE !== ($pos = elgg_strpos($haystack_lc, $word, $offset))) { $start = $pos - $min_match_context > 0 ? $pos - $min_match_context : 0; $starts[] = $start; $stop = $pos + $word_len + $min_match_context; $lengths[] = $stop - $start; $offset += $pos + $word_len; } } else { $pos = elgg_strpos($haystack_lc, $word); $start = $pos - $min_match_context > 0 ? $pos - $min_match_context : 0; $starts[] = $start; $stop = $pos + $word_len + $min_match_context; $lengths[] = $stop - $start; } } $offsets = search_consolidate_substrings($starts, $lengths); // figure out if we can adjust the offsets and lengths // in order to return more context $total_length = array_sum($offsets); $add_length = 0; if ($total_length < $max_length) { $add_length = floor(($max_length - $total_length) / count($offsets) / 2); $starts = array(); $lengths = array(); foreach ($offsets as $offset => $length) { $start = $offset - $add_length > 0 ? $offset - $add_length : 0; $length = $length + $add_length; $starts[] = $start; $lengths[] = $length; } $offsets = search_consolidate_substrings($starts, $lengths); } // sort by order of string size descending (which is roughly // the proximity of matched terms) so we can keep the // substrings with terms closest together and discard // the others as needed to fit within $max_length. arsort($offsets); $return_strs = array(); $total_length = 0; foreach ($offsets as $start => $length) { $string = trim(elgg_substr($haystack, $start, $length)); // continue past if adding this substring exceeds max length if ($total_length + $length > $max_length) { continue; } $total_length += $length; $return_strs[$start] = $string; } // put the strings in order of occurence ksort($return_strs); // add ...s where needed $return = implode('...', $return_strs); if (!array_key_exists(0, $return_strs)) { $return = "...{$return}"; } // add to end of string if last substring doesn't hit the end. $starts = array_keys($return_strs); $last_pos = $starts[count($starts) - 1]; if ($last_pos + elgg_strlen($return_strs[$last_pos]) < $haystack_length) { $return .= '...'; } $return = search_highlight_words($words, $return); return $return; }
function index_search() { $entityTypes = array(); if ($_GET['check']) { foreach ($_GET['check'] as $entityType) { $entityTypes[] = $entityType; } } // $search_type == all || entities || trigger plugin hook $search_type = get_input('search_type', 'all'); // @todo there is a bug in get_input that makes variables have slashes sometimes. // @todo is there an example query to demonstrate ^ // XSS protection is more important that searching for HTML. $query = stripslashes(get_input('index-query', get_input('tag', ''))); if (function_exists('mb_convert_encoding')) { $display_query = mb_convert_encoding($query, 'HTML-ENTITIES', 'UTF-8'); } else { // if no mbstring extension, we just strip characters $display_query = preg_replace("/[^-]/", "", $query); } $display_query = htmlspecialchars($display_query, ENT_QUOTES, 'UTF-8', false); // check that we have an actual query if (!$query) { $title = sprintf(elgg_echo('search:results'), "\"{$display_query}\""); $body = elgg_view_title(elgg_echo('search:search_error')); $body .= elgg_echo('search:no_query'); $layout = elgg_view_layout('one_sidebar', array('content' => $body)); echo elgg_view_page($title, $layout); return; } // get limit and offset. override if on search dashboard, where only 2 // of each most recent entity types will be shown. $limit = $search_type == 'all' ? 2 : get_input('limit', 10); $offset = $search_type == 'all' ? 0 : get_input('offset', 0); $order = get_input('order', 'desc'); if ($order != 'asc' && $order != 'desc') { $order = 'desc'; } // set up search params $params = array('query' => $query, 'offset' => $offset, 'limit' => $limit, 'sort' => $sort, 'order' => $order, 'search_type' => $search_type, 'type' => $entity_type, 'subtype' => $entity_subtype, 'owner_guid' => $owner_guid, 'container_guid' => $container_guid, 'pagination' => $search_type == 'all' ? FALSE : TRUE); $types = get_registered_entity_types(); //$types['object'] foreach ($types as $type => $subtypes) { //only include subtypes the user wishes to search for foreach ($subtypes as $key => $subtype) { $flag = false; error_log($type . $key . $subtype); foreach ($entityTypes as $entityType) { if ($subtype == $entityType) { $flag = true; } } if ($flag !== true) { //var_dump($types[$type][$key]); unset($types[$type][$key]); //$types = array_values($types); } } //only include types user wishes to search for - this is only for groups and users as they are not sub types $flag = false; if ($type != 'object') { foreach ($entityTypes as $entityType) { if ($type == $entityType) { $flag = true; } } if ($flag !== true) { unset($types[$type]); } } } // add sidebar items for all and native types // @todo should these maintain any existing type / subtype filters or reset? $data = htmlspecialchars(http_build_query(array('q' => $query, 'entity_subtype' => $entity_subtype, 'entity_type' => $entity_type, 'owner_guid' => $owner_guid, 'search_type' => 'all'))); $url = elgg_get_site_url() . "search?{$data}"; $menu_item = new ElggMenuItem('all', elgg_echo('all'), $url); elgg_register_menu_item('page', $menu_item); foreach ($types as $type => $subtypes) { // @todo when using index table, can include result counts on each of these. if (is_array($subtypes) && count($subtypes)) { foreach ($subtypes as $subtype) { $label = "item:{$type}:{$subtype}"; $data = htmlspecialchars(http_build_query(array('q' => $query, 'entity_subtype' => $subtype, 'entity_type' => $type, 'owner_guid' => $owner_guid, 'search_type' => 'entities', 'friends' => $friends))); $url = elgg_get_site_url() . "search?{$data}"; $menu_item = new ElggMenuItem($label, elgg_echo($label), $url); elgg_register_menu_item('page', $menu_item); } } else { $label = "item:{$type}"; $data = htmlspecialchars(http_build_query(array('q' => $query, 'entity_type' => $type, 'owner_guid' => $owner_guid, 'search_type' => 'entities', 'friends' => $friends))); $url = elgg_get_site_url() . "search?{$data}"; $menu_item = new ElggMenuItem($label, elgg_echo($label), $url); elgg_register_menu_item('page', $menu_item); } } // start the actual search $results_html = ''; if ($search_type == 'all' || $search_type == 'entities') { // to pass the correct current search type to the views $current_params = $params; $current_params['search_type'] = 'entities'; // foreach through types. // if a plugin returns FALSE for subtype ignore it. // if a plugin returns NULL or '' for subtype, pass to generic type search function. // if still NULL or '' or empty(array()) no results found. (== don't show??) foreach ($types as $type => $subtypes) { if ($search_type != 'all' && $entity_type != $type) { continue; } if (is_array($subtypes) && count($subtypes)) { foreach ($subtypes as $subtype) { // no need to search if we're not interested in these results // @todo when using index table, allow search to get full count. if ($search_type != 'all' && $entity_subtype != $subtype) { continue; } $current_params['subtype'] = $subtype; $current_params['type'] = $type; $results = elgg_trigger_plugin_hook('search', "{$type}:{$subtype}", $current_params, NULL); if ($results === FALSE) { // someone is saying not to display these types in searches. continue; } elseif (is_array($results) && !count($results)) { // no results, but results searched in hook. } elseif (!$results) { // no results and not hooked. use default type search. // don't change the params here, since it's really a different subtype. // Will be passed to elgg_get_entities(). $results = elgg_trigger_plugin_hook('search', $type, $current_params, array()); } if (is_array($results['entities']) && $results['count']) { if ($view = search_get_search_view($current_params, 'list')) { $results_html .= elgg_view($view, array('results' => $results, 'params' => $current_params)); } } } } // pull in default type entities with no subtypes $current_params['type'] = $type; $current_params['subtype'] = ELGG_ENTITIES_NO_VALUE; $results = elgg_trigger_plugin_hook('search', $type, $current_params, array()); if ($results === FALSE) { // someone is saying not to display these types in searches. continue; } if (is_array($results['entities']) && $results['count']) { if ($view = search_get_search_view($current_params, 'list')) { $results_html .= elgg_view($view, array('results' => $results, 'params' => $current_params)); } } } } // highlight search terms if ($search_type == 'tags') { $searched_words = array($display_query); } else { $searched_words = search_remove_ignored_words($display_query, 'array'); } $highlighted_query = search_highlight_words($searched_words, $display_query); $body = elgg_view_title(elgg_echo('search:results', array("\"{$highlighted_query}\""))); if (!$results_html) { $body .= elgg_view('search/no_results'); } else { $body .= $results_html; } // this is passed the original params because we don't care what actually // matched (which is out of date now anyway). // we want to know what search type it is. $layout_view = search_get_search_view($params, 'layout'); $layout = elgg_view($layout_view, array('params' => $params, 'body' => $body)); $title = elgg_echo('search:results', array("\"{$display_query}\"")); echo elgg_view_page($title, $layout); }
if ($results === FALSE) { // someone is saying not to display these types in searches. continue; } if (isset($results['entities']) && is_array($results['entities']) && $results['count']) { if ($view = search_get_search_view($current_params, 'list')) { $search_result_counters["search_types:" . $type] = $results['count']; $results_html .= elgg_view($view, array('results' => $results, 'params' => $current_params)); } } } } } // highlight search terms $searched_words = search_remove_ignored_words($display_query, 'array'); $highlighted_query = search_highlight_words($searched_words, $display_query); $body = elgg_view_title(elgg_echo('search:results', array("\"{$highlighted_query}\""))); // add search form if (!elgg_is_xhr()) { $body .= elgg_view_form("search_advanced/search", array("action" => "search", "method" => "GET", "disable_security" => true), $params); } if (!$results_html) { $body .= elgg_view('search/no_results'); } else { $body .= $results_html; } // moved to bottom so we can use search result count in labels // add sidebar items for all and native types // @todo should these maintain any existing type / subtype filters or reset? // JD: yeah they should $data = htmlspecialchars(http_build_query(array('q' => $query, 'search_type' => 'all')));
<?php $q = sanitise_string(get_input("q")); $limit = max((int) get_input("limit", 5), 1); $page_owner_guid = (int) get_input("page_owner_guid"); $result = array(); if (!empty($q)) { // keywords (tags, categories) $keywords = search_advanced_get_keywords(); if (!empty($keywords)) { foreach ($keywords as $content) { if (stristr($content, $q)) { $result[] = array("type" => "tag", "content" => search_highlight_words(array($q), $content), "value" => $content, "href" => elgg_normalize_url("search?q=" . urlencode($content))); } } } // look for users $options = array(); $options['query'] = $q; $options['type'] = "user"; $options['limit'] = $limit; $results = elgg_trigger_plugin_hook('search', 'user', $options, array()); $user_count = $results['count']; $users = $results['entities']; if ($user_count > 0) { $result[] = array("type" => "placeholder", "content" => "<label>" . elgg_echo("item:user") . " (" . $user_count . ")</label>", "href" => elgg_normalize_url("search?entity_type=user&search_type=entities&q=" . $q)); foreach ($users as $user) { $result[] = array("type" => "user", "value" => $user->name, "href" => $user->getURL(), "content" => elgg_view("search_advanced/autocomplete/user", array("entity" => $user))); } } // search for groups