Created
April 11, 2012 20:23
-
-
Save deepagupta/2362199 to your computer and use it in GitHub Desktop.
search for tags when a partial string is provided
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @auth: d.gupta | |
* @date: Apr/11/12 | |
* @desc: This file (start.php) along a manifest file constitute a plugin namely "search_extension" that extends the "search" | |
The core plugin "search" displays tag results only if the inputted string matches the tags exactly and completely | |
[concerned code: search_tag_hook(..) in /mod/search/search_hooks.php] | |
However, the following code overrides it by correctly displaying the tag-search-results even when the searched string is a substring of the tag | |
ANY IMPROVEMENTS/FEEDBACK IS HIGHLY APPRECIATED. | |
Why this isn't posted as a plugin yet: | |
From the comments, it seems that there is work and improvements already on its way by the core developers. I am hopeful | |
to have this worked out in the future versions of the Elgg thereby not requiring this as a plugin at all. Or else, if | |
not, I look forward to have some feedback before going down that path | |
*/ | |
elgg_register_event_handler('init','system','search_extension_init'); | |
function search_extension_init(){ | |
elgg_unregister_plugin_hook_handler('search','tags','search_tags_hook'); | |
elgg_register_plugin_hook_handler('search', 'tags', 'search_extension_tags_hook'); | |
} | |
/** | |
* Return default results for searches on tags. | |
* | |
* @param unknown_type $hook | |
* @param unknown_type $type | |
* @param unknown_type $value | |
* @param unknown_type $params | |
* @return unknown_type | |
*/ | |
function search_extension_tags_hook($hook, $type, $value, $params) { | |
$db_prefix = elgg_get_config('dbprefix'); | |
static $iteration = 0; | |
$iteration++; | |
$valid_tag_names = elgg_get_registered_tag_metadata_names(); | |
// @todo will need to split this up to support searching multiple tags at once. | |
$query = sanitise_string($params['query']); | |
// if passed a tag metadata name, only search on that tag name. | |
// tag_name isn't included in the params because it's specific to | |
// tag searches. | |
if ($tag_names = get_input('tag_names')) { | |
if (is_array($tag_names)) { | |
$search_tag_names = $tag_names; | |
} else { | |
$search_tag_names = array($tag_names); | |
} | |
// check these are valid to avoid arbitrary metadata searches. | |
foreach ($search_tag_names as $i => $tag_name) { | |
if (!in_array($tag_name, $valid_tag_names)) { | |
unset($search_tag_names[$i]); | |
} | |
} | |
} else { | |
$search_tag_names = $valid_tag_names; | |
} | |
if (!$search_tag_names) { | |
return array('entities' => array(), 'count' => $count); | |
} | |
// don't use elgg_get_entities_from_metadata() here because of | |
// performance issues. since we don't care what matches at this point | |
// use an IN clause to grab everything that matches at once and sort | |
// out the matches later. | |
$params['joins'][] = "JOIN {$db_prefix}metadata md on e.guid = md.entity_guid"; | |
$params['joins'][] = "JOIN {$db_prefix}metastrings msn on md.name_id = msn.id"; | |
$params['joins'][] = "JOIN {$db_prefix}metastrings msv on md.value_id = msv.id"; | |
$access = get_access_sql_suffix('md'); | |
$sanitised_tags = array(); | |
foreach ($search_tag_names as $tag) { | |
$sanitised_tags[] = '"' . sanitise_string($tag) . '"'; | |
} | |
$tags_in = implode(',', $sanitised_tags); | |
/** @auth: d.gupta @date: Apr/11/12 | |
* changed query to LIKE %query% so as to match tags with partial string | |
*/ | |
$params['wheres'][] = "(msn.string IN ($tags_in) AND msv.string LIKE '%$query%' AND $access)"; | |
$params['count'] = TRUE; | |
$count = elgg_get_entities($params); | |
// no need to continue if nothing here. | |
if (!$count) { | |
return array('entities' => array(), 'count' => $count); | |
} | |
$params['count'] = FALSE; | |
$entities = elgg_get_entities($params); | |
// add the volatile data for why these entities have been returned. | |
foreach ($entities as $entity) { | |
$matched_tags_strs = array(); | |
// get tags for each tag name requested to find which ones matched. | |
foreach ($search_tag_names as $tag_name) { | |
$tags = $entity->getTags($tag_name); | |
// @todo make one long tag string and run this through the highlight | |
// function. This might be confusing as it could chop off | |
// the tag labels. | |
/* @auth: d.gupta @date: Apr/11/12 ----------- */ | |
/* @desc: this is done for getting display of tags-search-result right. following code modified from the original for replacing the condtion: "in_array(strtolower($query), array_map('strtolower', $tags))" by our calculated boolean: "$query_is_in_tags" (boolean)" | |
* how this makes a difference: our calculated condition ($query_is_in_tags) returns true if the searched string is contained/is a substring of the actual tag of the entity | |
*the former/orginial code displayed & highlighted the searched tag only if the searched string exactly matched the entity's tag whereas | |
*/ | |
$query_lower = strtolower($query); | |
$tags_lower = array_map('strtolower',$tags); | |
$query_is_in_tags = false; | |
foreach($tags_lower as $tag_element){ | |
if(strpos($tag_element,$query_lower)>=0){ | |
$query_is_in_tags = true; | |
} | |
} | |
if ($query_is_in_tags) { | |
// ------------------------------------------------------// | |
if (is_array($tags)) { | |
$tag_name_str = elgg_echo("tag_names:$tag_name"); | |
$matched_tags_strs[] = "$tag_name_str: " . implode(', ', $tags); | |
} | |
} | |
} | |
// different entities have different titles | |
switch($entity->type) { | |
case 'site': | |
case 'user': | |
case 'group': | |
$title_tmp = $entity->name; | |
break; | |
case 'object': | |
$title_tmp = $entity->title; | |
break; | |
} | |
// Nick told me my idea was dirty, so I'm hard coding the numbers. | |
$title_tmp = strip_tags($title_tmp); | |
if (elgg_strlen($title_tmp) > 297) { | |
$title_str = elgg_substr($title_tmp, 0, 297) . '...'; | |
} else { | |
$title_str = $title_tmp; | |
} | |
$desc_tmp = strip_tags($entity->description); | |
if (elgg_strlen($desc_tmp) > 297) { | |
$desc_str = elgg_substr($desc_tmp, 0, 297) . '...'; | |
} else { | |
$desc_str = $desc_tmp; | |
} | |
$tags_str = implode('. ', $matched_tags_strs); | |
$tags_str = search_get_highlighted_relevant_substrings($tags_str, $params['query']); | |
$entity->setVolatileData('search_matched_title', $title_str); | |
$entity->setVolatileData('search_matched_description', $desc_str); | |
$entity->setVolatileData('search_matched_extra', $tags_str); | |
} | |
return array( | |
'entities' => $entities, | |
'count' => $count, | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment