From 5d96c9b12fe0ea953ef95af952e588a1898ef1fc Mon Sep 17 00:00:00 2001 From: brettp Date: Fri, 6 Nov 2009 01:46:36 +0000 Subject: Updated search for FTS. git-svn-id: http://code.elgg.org/elgg/trunk@3619 36083f99-b078-4883-b0ff-0f9b5a30f544 --- mod/search/index.php | 296 ++++++++++++++++------- mod/search/start.php | 160 ++++++++++-- mod/search/views/default/search/css.php | 23 +- mod/search/views/default/search/listing.php | 67 +++-- mod/search/views/default/search/startblurb.php | 8 +- mod/search/views/default/search/tags/listing.php | 55 +++++ 6 files changed, 474 insertions(+), 135 deletions(-) create mode 100644 mod/search/views/default/search/tags/listing.php (limited to 'mod/search') diff --git a/mod/search/index.php b/mod/search/index.php index 7cbf6121c..30f33f9f1 100644 --- a/mod/search/index.php +++ b/mod/search/index.php @@ -1,6 +1,136 @@ $query, + 'offset' => $offset, + 'limit' => $limit, + 'search_type' => $search_type, + 'type' => $type, + 'subtype' => $subtype, + 'tag_type' => $tag_type, + 'owner_guid' => $owner_guid, + 'friends' => $friends +); + +$results_html = ''; +if ($search_type == 'entities' || $search_type == 'all') { + $types = get_registered_entity_types(); + + // to pass the correct search type to the views + $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 (is_array($subtypes) && count($subtypes)) { + foreach ($subtypes as $subtype) { + $params['subtype'] = $subtype; + $params['type'] = $type; + + $entities = trigger_plugin_hook('search', "$type:$subtype", $params, NULL); + if ($entities === FALSE) { + // someone is saying not to display these types in searches. + continue; + } elseif (is_array($entities) && !count($entities)) { + // no results, but results searched in hook. + } elseif (!$entities) { + // 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 = trigger_plugin_hook('search', $type, $params, array()); + } + + if (is_array($results['entities']) && $results['count']) { + $results_html .= search_get_listing_html($results['entities'], $results['count'], $params); + } + } + } + + // pull in default type entities with no subtypes + // @todo this might currently means "all entities regardless of subtype" + $params['type'] = $type; + $params['subtype'] = 0; + + $results = trigger_plugin_hook('search', $type, $params, array()); + if ($results === FALSE) { + // someone is saying not to display these types in searches. + continue; + } + + if (is_array($results['entities']) && $results['count']) { + $results_html .= search_get_listing_html($results['entities'], $results['count'], $params); + } + } +} + +// call custom searches +if ($search_type == 'all' || $search_type != 'entities') { + // get custom search types + $types = trigger_plugin_hook('search_types', 'get_types', $params, array()); + + if (is_array($types)) { + foreach ($types as $type) { + $params['search_type'] = $type; + unset($params['subtype']); + + $results = trigger_plugin_hook('search', $type, $params, array()); + + if ($results === FALSE) { + // someone is saying not to display these types in searches. + continue; + } + + if (is_array($results['entities']) && $results['count']) { + $results_html .= search_get_listing_html($results['entities'], $results['count'], $params); + } + } + } +} + +//if ($search_type !== 'all') { +// var_dump('here'); +// $entities = trigger_plugin_hook('search', $search_type, '', $return); +//} +/* + +call search_section_start to display long bar with types and titles +call search + + + +*/ + +$layout = elgg_view_layout('single_column', '', $results_html); + +page_draw($title, $layout); + + + + + + + +return; + + +/** Main search page */ global $CONFIG; @@ -8,28 +138,25 @@ $tag = get_input('tag'); $offset = get_input('offset', 0); $viewtype = get_input('search_viewtype','list'); if ($viewtype == 'gallery') { - $limit = get_input('limit', 12); // 10 items in list view + $limit = get_input('limit', 12); // 10 items in list view } else { - $limit = get_input('limit', 10); // 12 items in gallery view + $limit = get_input('limit', 10); // 12 items in gallery view } $searchtype = get_input('searchtype', 'all'); -$object_type = get_input('object_type', ''); +$type = get_input('type', ''); $subtype = get_input('subtype', ''); $owner_guid = get_input('owner_guid', ''); $tagtype = get_input('tagtype', ''); $friends = (int)get_input('friends', 0); +$title = sprintf(elgg_echo('searchtitle'), $tag); - -$title = sprintf(elgg_echo('searchtitle'), $tag); - - -if (substr_count($owner_guid,',')) { - $owner_guid_array = explode(",",$owner_guid); +if (substr_count($owner_guid, ',')) { + $owner_guid_array = explode(',', $owner_guid); } else { $owner_guid_array = $owner_guid; } if ($friends > 0) { - if ($friends = get_user_friends($friends,'',9999)) { + if ($friends = get_user_friends($friends, '', 9999)) { $owner_guid_array = array(); foreach($friends as $friend) { $owner_guid_array[] = $friend->guid; @@ -40,107 +167,110 @@ if ($friends > 0) { } // Set up submenus -if ($object_types = get_registered_entity_types()) { - - foreach($object_types as $ot => $subtype_array) { - if (is_array($subtype_array) && sizeof($subtype_array)) +if ($types = get_registered_entity_types()) { + foreach($types as $ot => $subtype_array) { + if (is_array($subtype_array) && count($subtype_array)) { foreach($subtype_array as $object_subtype) { $label = 'item:' . $ot; - if (!empty($object_subtype)) $label .= ':' . $object_subtype; - add_submenu_item(elgg_echo($label), $CONFIG->wwwroot . "pg/search/?tag=". urlencode($tag) ."&subtype=" . $object_subtype . "&object_type=". urlencode($ot) ."&tagtype=" . urlencode($md_type) . "&owner_guid=" . urlencode($owner_guid)); + if (!empty($object_subtype)) { + $label .= ':' . $object_subtype; + } + + $data = http_build_query(array( + 'tag' => urlencode($tag), + 'subtype' => $object_subtype, + 'type' => urlencode($ot), + //'tagtype' => urlencode($md_type), + 'owner_guid' => urlencode($owner_guid) + )); + + $url = "{$CONFIG->wwwroot}pg/search/?$data"; + + add_submenu_item(elgg_echo($label), $url); } + } } - add_submenu_item(elgg_echo('all'), $CONFIG->wwwroot . "pg/search/?tag=". urlencode($tag) ."&owner_guid=" . urlencode($owner_guid)); - + + $data = http_build_query(array( + 'tag' => urlencode($tag), + 'owner_guid' => urlencode($owner_guid) + )); + + add_submenu_item(elgg_echo('all'), "{$CONFIG->wwwroot}pg/search/?$data"); +} + +// pull in search types for external or aggregated searches. +if ($search_types = trigger_plugin_hook('search', 'types', '', NULL, array())) { + } $body = ''; if (!empty($tag)) { + // start with blank results. + $results = array( + 'entities' => array(), + 'total' => 0 + ); + + // do the actual searchts + $params = array( + 'tag' => $tag, + 'offset' => $offset, + 'limit' => $limit, + 'searchtype' => $searchtype, + 'type' => $type, + 'subtype' => $subtype, + 'tagtype' => $tagtype, + 'owner_guid' => $owner_guid_array + ); + + $results = trigger_plugin_hook('search', 'entities', $params, $results); - // blank the results to start off - $results = new stdClass(); - $results->entities = array(); - $results->total = 0; - - // do the actual search - $results = trigger_plugin_hook('search:entities', '', array('tag' => $tag, - 'offset' => $offset, - 'limit' => $limit, - 'searchtype' => $searchtype, - 'object_type' => $object_type, - 'subtype' => $subtype, - 'tagtype' => $tagtype, - 'owner_guid' => $owner_guid_array - ), - $results); - - /* // this piece is for future work, to setup submenus for searchtypes - $searchtypes = trigger_plugin_hook('search:types', '', NULL, array()); - add_submenu_item(elgg_echo('search:type:all'), - $CONFIG->wwwroot . "pg/search/?tag=". urlencode($tag) ."&searchtype=all"); - - foreach ($searchtypes as $st) { - add_submenu_item(elgg_echo('search:type:' . $st), - $CONFIG->wwwroot . "pg/search/?tag=". urlencode($tag) ."&searchtype=" . $st); - } - */ - - - if (empty($objecttype) && empty($subtype)) { - $title = sprintf(elgg_echo('searchtitle'),$tag); + if (empty($type) && empty($subtype)) { + $title = sprintf(elgg_echo('searchtitle'),$tag); } else { - if (empty($objecttype)) $objecttype = 'object'; - $itemtitle = 'item:' . $objecttype; - if (!empty($subtype)) $itemtitle .= ':' . $subtype; + if (empty($type)) { + $type = 'object'; + } + $itemtitle = 'item:' . $type; + if (!empty($subtype)) { + $itemtitle .= ':' . $subtype; + } $itemtitle = elgg_echo($itemtitle); $title = sprintf(elgg_echo('advancedsearchtitle'),$itemtitle,$tag); } - - - - - //print_r($results); $body .= elgg_view_title($title); // elgg_view_title(sprintf(elgg_echo('searchtitle'),$tag)); // call the old (now-deprecated) search hook here $body .= trigger_plugin_hook('search','',$tag, ''); - $body .= elgg_view('search/startblurb', array('tag' => $tag)); + $body .= elgg_view('search/startblurb', array('query' => $query)); if ($results->total > 0) { - - - $body .= elgg_view('search/entity_list', array('entities' => $results->entities, - 'count' => $results->total, - 'offset' => $offset, - 'limit' => $limit, - 'baseurl' => $_SERVER['REQUEST_URI'], - 'fullview' => false, - 'context' => 'search', - 'viewtypetoggle' => true, - 'viewtype' => $viewtype, - 'pagination' => true - )); + $body .= elgg_view('search/entity_list', array( + 'entities' => $results->entities, + 'count' => $results->total, + 'offset' => $offset, + 'limit' => $limit, + 'baseurl' => $_SERVER['REQUEST_URI'], + 'fullview' => false, + 'context' => 'search', + 'viewtypetoggle' => true, + 'viewtype' => $viewtype, + 'pagination' => true + )); } else { - $body .= elgg_view('page_elements/contentwrapper', array('body' => elgg_echo('search:noresults'))); + $body .= elgg_view('page_elements/contentwrapper', array('body' => elgg_echo('search:noresults'))); } - - - elgg_view_entity_list($results->entities, count($results->entities), 0, count($results->entities), false); } else { // if no tag was given, give the user a box to input a search term $body .= elgg_view_title(elgg_echo('search:enterterm')); $body .= elgg_view('page_elements/contentwrapper', array('body' => '
' . elgg_view('page_elements/searchbox') . '
')); - - } -$layout = elgg_view_layout('two_column_left_sidebar','',$body); - - -page_draw($title, $layout); +$layout = elgg_view_layout('two_column_left_sidebar','',$body); -?> \ No newline at end of file +page_draw($title, $layout); \ No newline at end of file diff --git a/mod/search/start.php b/mod/search/start.php index 24b038c7a..4bd342285 100644 --- a/mod/search/start.php +++ b/mod/search/start.php @@ -1,8 +1,8 @@ , The MITRE Corporation @@ -14,21 +14,13 @@ * */ function search_init() { - global $CONFIG; - // page handler for search actions and results register_page_handler('search','search_page_handler'); - // hook into the search callback to use the metadata system (this is the part that will go away!) - register_plugin_hook('search:entities', 'all', 'search_original_hook'); - - // list of available search types should include our base parts - register_plugin_hook('searchtypes', 'all', 'search_base_search_types_hook'); - // add in CSS for search elements extend_view('css', 'search/css'); } - + /** * Page handler for search * @@ -36,9 +28,9 @@ function search_init() { */ function search_page_handler($page) { global $CONFIG; - + if(!get_input('tag')) { - set_input('tag', $page[0]); + set_input('tag', $page[0]); } include_once($CONFIG->path . "mod/search/index.php"); @@ -47,13 +39,17 @@ function search_page_handler($page) { /** * Core search hook. * Returns an object with two parts: - * ->entities: an array of instantiated entities that have been decorated with + * ->entities: an array of instantiated entities that have been decorated with * volatile "search" data indicating what they matched. These are * the entities to be displayed to the user on this page. * ->total: total number of entities overall. This function can update this * limit to ask for more pages in the pagination. */ function search_original_hook($hook, $type, $returnvalue, $params) { + global $CONFIG; + + var_dump($CONFIG->hooks); + $tag = $params['tag']; $offset = $params['offset']; // starting page $limit = $params['limit']; // number per page @@ -63,9 +59,21 @@ function search_original_hook($hook, $type, $returnvalue, $params) { $owner_guid = $params['owner_guid']; $tagtype = $params['tagtype']; - $count = get_entities_from_metadata($tagtype, elgg_strtolower($tag), $object_type, $subtype, $owner_guid, $limit, $offset, "", 0, TRUE, FALSE); + $count = get_entities_from_metadata($tagtype, elgg_strtolower($tag), $object_type, $subtype, $owner_guid, $limit, $offset, "", 0, TRUE, FALSE); $ents = get_entities_from_metadata($tagtype, elgg_strtolower($tag), $object_type, $subtype, $owner_guid, $limit, $offset, "", 0, FALSE, FALSE); +// $options = array( +// 'metadata_name_value_pair' => array('name' => $params['tagtype'], 'value' => $params['tag'], 'case_sensitive' => false), +// 'offset' => $params['offset'], +// 'limit' => $params['limit'], +// 'type' => $params['object_type'], +// 'subtype' => $params['subtype'], +// 'owner_guid' => $params['owner_guid'] +// ); +// +// $count = elgg_get_entities_from_metadata(array_merge($options, array('count' => TRUE))); +// $entities = elgg_get_entities_from_metadata($options); + /* * Foreach entity * get the metadata keys @@ -98,6 +106,26 @@ function search_original_hook($hook, $type, $returnvalue, $params) { return $returnvalue; } +/** + * Provides default search for registered entity subtypes. + * Entity types should be dealt with in the entity classes. (Objects are an exception). + * + * @param unknown_type $hook + * @param unknown_type $type + * @param unknown_type $returnvalue + * @param unknown_type $params + * @return unknown_type + */ +function search_registered_entities($hook, $type, $returnvalue, $params) { + $entity_types = get_registered_entity_types(); + foreach ($entity_types as $type => $subtypes) { + if (is_array($subtypes) && count($subtypes)) { + + } + + } +} + /** * return our base search types (right now, we have none) */ @@ -109,8 +137,104 @@ function search_base_search_types_hook($hook, $type, $returnvalue, $params) { return $returnvalue; } -/** Register init system event **/ -register_elgg_event_handler('init','system','search_init'); +/** + * Returns a matching string with $context amount of context, optionally + * surrounded by $before and $after. + * + * If no match is found, restricts string to $context*2 starting from strpos 0. + * + * @param str $haystack + * @param str $needle + * @param str $before + * @param str $after + * @param str $context + * @return str + */ +function search_get_relevant_substring($haystack, $needle, $before = '', $after = '', $context = 75) { + $haystack = strip_tags($haystack); + $needle = strip_tags($needle); + + $pos = strpos(strtolower($haystack), strtolower($needle)); + + if ($pos === FALSE) { + $str = substr($haystack, 0, $context*2); + if (strlen($haystack) > $context*2) { + $str .= '...'; + } + + return $str; + } + + $start_pos = $pos - $context; + + if ($start_pos < 0) { + $start_pos = 0; + } + + // get string from -context to +context + $matched = substr($haystack, $start_pos, $context*2); + + // add elipses to front. + if ($start_pos > 0) { + $matched = "...$matched"; + } + + // add elipses to end. + if ($start_pos + $context < strlen($haystack)) { + $matched = "$matched..."; + } + + // surround if needed + if ($before || $after) { + $matched = str_ireplace($needle, $before . $needle . $after, $matched); + } + + return $matched; +} + + + +function search_get_listing_html($entities, $count, $params) { + if (!is_array($entities) || !$count) { + return FALSE; + } + + $view_order = array(); + + // check if there's a special search view for this type:subtype + if (isset($params['type']) && $params['type'] && isset($params['subtype']) && $params['subtype']) { + $view_order[] = "search/{$params['type']}/{$params['subtype']}/listing"; + } + + // also check for the default type + if (isset($params['type']) && $params['type']) { + $view_order[] = "search/{$params['type']}/listing"; + } + + // check search types + if (isset($params['search_type']) && $params['search_type']) { + $view_order[] = "search/{$params['search_type']}/listing"; + } + + // finally default to a search listing default + $view_order[] = "search/listing"; + + $vars = array( + 'entities' => $entities, + 'count' => $count, + 'params' => $params + ); + + foreach ($view_order as $view) { + if (elgg_view_exists($view)) { + return elgg_view($view, $vars); + } + } + + return FALSE; +} + +/** Register init system event **/ -?> +register_elgg_event_handler('init','system','search_init'); \ No newline at end of file diff --git a/mod/search/views/default/search/css.php b/mod/search/views/default/search/css.php index 27b532727..936fe5c9d 100644 --- a/mod/search/views/default/search/css.php +++ b/mod/search/views/default/search/css.php @@ -1,4 +1,4 @@ -.searchtype { +.searchtype { background: #FFFACD; color: black; } @@ -9,8 +9,21 @@ padding: 4px; margin: 6px; } +.searchListing { + display: block; + margin-bottom: 2em; +} + +.searchMatch { + background-color: #FFFF66; +} + +.searchTitle { + text-decoration: underline; +} + #searchform input.search_input { - -webkit-border-radius: 4px; + -webkit-border-radius: 4px; -moz-border-radius: 4px; background-color:#FFFFFF; border:1px solid #BBBBBB; @@ -23,7 +36,7 @@ margin: 6px; height:12px; } #searchform input.search_submit_button { - -webkit-border-radius: 4px; + -webkit-border-radius: 4px; -moz-border-radius: 4px; color:#333333; background: #cccccc; @@ -44,7 +57,7 @@ margin: 6px; .search_listing { display: block; - -webkit-border-radius: 8px; + -webkit-border-radius: 8px; -moz-border-radius: 8px; background:white; margin:0 10px 5px 10px; @@ -58,7 +71,7 @@ margin: 6px; /* override the entity container piece */ .search_listing .entity_listing { - -webkit-border-radius: 0px; + -webkit-border-radius: 0px; -moz-border-radius: 0px; background: transparent; margin: 0; diff --git a/mod/search/views/default/search/listing.php b/mod/search/views/default/search/listing.php index e3ad91ba8..2ed657547 100644 --- a/mod/search/views/default/search/listing.php +++ b/mod/search/views/default/search/listing.php @@ -1,35 +1,54 @@ - /** - * Elgg search listing - * - * @package Elgg - * @subpackage Core +
- * @author Curverider Ltd + +$title_str = elgg_echo("item:{$vars['params']['type']}:{$vars['params']['subtype']}"); +$body = elgg_view_title($title_str); -
- - $body)); -if ($vars['search_types'] && is_array($vars['search_types'])) { - echo '
' . elgg_echo('search:matched'); - foreach ($vars['search_types'] as $st) { - echo '' . elgg_echo($st) . ' '; +foreach ($entities as $entity) { + if ($owner = $entity->getOwnerEntity()) { + $owner_icon = $owner->getIcon('tiny'); + $icon = ""; + } else { + $icon = ''; } - echo '
'; - + $title = $entity->getVolatileData('search_matched_title'); + $description = $entity->getVolatileData('search_matched_description'); + $url = $entity->getURL(); + $title = "$title"; + $tc = $entity->time_created; + $tu = $entity->time_updated; + $time = friendly_time(($tu > $tc) ? $tu : $tc); + + echo <<<___END + +

$title

+ + $description
+ $icon - $time - More $title_str - +
+
+___END; } - - - ?> -
+
\ No newline at end of file diff --git a/mod/search/views/default/search/startblurb.php b/mod/search/views/default/search/startblurb.php index 0115438f2..82d2d62d1 100644 --- a/mod/search/views/default/search/startblurb.php +++ b/mod/search/views/default/search/startblurb.php @@ -7,9 +7,7 @@ */ ?>
- +
\ No newline at end of file diff --git a/mod/search/views/default/search/tags/listing.php b/mod/search/views/default/search/tags/listing.php new file mode 100644 index 000000000..a5a33c4a4 --- /dev/null +++ b/mod/search/views/default/search/tags/listing.php @@ -0,0 +1,55 @@ + + +
+ + $body)); + +foreach ($entities as $entity) { + if ($owner = $entity->getOwnerEntity()) { + $owner_icon = $owner->getIcon('tiny'); + $icon = ""; + } else { + $icon = ''; + } + $tags = $entity->getVolatileData('search_matched_tags'); + + $entity_html = elgg_view_entity($entity); + $url = $entity->getURL(); + $title = "$title"; + $tc = $entity->time_created; + $tu = $entity->time_updated; + $time = friendly_time(($tu > $tc) ? $tu : $tc); + + echo <<<___END + +

$title

+ + $entity_html + $tags + +
+___END; +} + +?> +
\ No newline at end of file -- cgit v1.2.3