Esempio n. 1
0
/**
 * Get entities with tags that match the search parameters.
 *
 * @param string $hook   Hook name
 * @param string $type   Hook type
 * @param array  $value  Empty array
 * @param array  $params Search parameters
 * @return array
 */
function search_tags_hook($hook, $type, $value, $params)
{
    $params['joins'] = (array) elgg_extract('joins', $params, array());
    $params['wheres'] = (array) elgg_extract('wheres', $params, array());
    $db_prefix = elgg_get_config('dbprefix');
    $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 = _elgg_get_access_where_sql(array('table_alias' => 'md'));
    $sanitised_tags = array();
    foreach ($search_tag_names as $tag) {
        $sanitised_tags[] = '"' . sanitise_string($tag) . '"';
    }
    $tags_in = implode(',', $sanitised_tags);
    $params['wheres'][] = "(msn.string IN ({$tags_in}) AND msv.string = '{$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;
    if (isset($params['sort']) || !isset($params['order_by'])) {
        $params['order_by'] = search_get_order_by_sql('e', null, $params['sort'], $params['order']);
    }
    $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.
            if (in_array(strtolower($query), array_map('strtolower', $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'], 30, 300, true);
        $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);
}
Esempio n. 2
0
/**
 * Get comments that match the search parameters.
 *
 * @param string $hook   Hook name
 * @param string $type   Hook type
 * @param array  $value  Empty array
 * @param array  $params Search parameters
 * @return array
 */
function search_comments_hook($hook, $type, $value, $params)
{
    $db_prefix = elgg_get_config('dbprefix');
    $query = sanitise_string($params['query']);
    $limit = sanitise_int($params['limit']);
    $offset = sanitise_int($params['offset']);
    $params['annotation_names'] = array('generic_comment', 'group_topic_post');
    $params['joins'] = array("JOIN {$db_prefix}annotations a on e.guid = a.entity_guid", "JOIN {$db_prefix}metastrings msn on a.name_id = msn.id", "JOIN {$db_prefix}metastrings msv on a.value_id = msv.id");
    $fields = array('string');
    // force IN BOOLEAN MODE since fulltext isn't
    // available on metastrings (and boolean mode doesn't need it)
    $search_where = search_get_where_sql('msv', $fields, $params, FALSE);
    $container_and = '';
    if ($params['container_guid'] && $params['container_guid'] !== ELGG_ENTITIES_ANY_VALUE) {
        $container_and = 'AND e.container_guid = ' . sanitise_int($params['container_guid']);
    }
    $e_access = get_access_sql_suffix('e');
    $a_access = get_access_sql_suffix('a');
    // @todo this can probably be done through the api..
    $q = "SELECT count(DISTINCT a.id) as total FROM {$db_prefix}annotations a\n\t\tJOIN {$db_prefix}metastrings msn ON a.name_id = msn.id\n\t\tJOIN {$db_prefix}metastrings msv ON a.value_id = msv.id\n\t\tJOIN {$db_prefix}entities e ON a.entity_guid = e.guid\n\t\tWHERE msn.string IN ('generic_comment', 'group_topic_post')\n\t\t\tAND ({$search_where})\n\t\t\tAND {$e_access}\n\t\t\tAND {$a_access}\n\t\t\t{$container_and}\n\t\t";
    if (!($result = get_data($q))) {
        return FALSE;
    }
    $count = $result[0]->total;
    // don't continue if nothing there...
    if (!$count) {
        return array('entities' => array(), 'count' => 0);
    }
    // no full text index on metastrings table
    if ($params['sort'] == 'relevance') {
        $params['sort'] = 'created';
    }
    $order_by = search_get_order_by_sql('a', null, $params['sort'], $params['order']);
    if ($order_by) {
        $order_by = "ORDER BY {$order_by}";
    }
    $q = "SELECT DISTINCT a.*, msv.string as comment FROM {$db_prefix}annotations a\n\t\tJOIN {$db_prefix}metastrings msn ON a.name_id = msn.id\n\t\tJOIN {$db_prefix}metastrings msv ON a.value_id = msv.id\n\t\tJOIN {$db_prefix}entities e ON a.entity_guid = e.guid\n\t\tWHERE msn.string IN ('generic_comment', 'group_topic_post')\n\t\t\tAND ({$search_where})\n\t\t\tAND {$e_access}\n\t\t\tAND {$a_access}\n\t\t\t{$container_and}\n\t\t\n\t\t{$order_by}\n\t\tLIMIT {$offset}, {$limit}\n\t\t";
    $comments = get_data($q);
    // @todo if plugins are disabled causing subtypes
    // to be invalid and there are comments on entities of those subtypes,
    // the counts will be wrong here and results might not show up correctly,
    // especially on the search landing page, which only pulls out two results.
    // probably better to check against valid subtypes than to do what I'm doing.
    // need to return actual entities
    // add the volatile data for why these entities have been returned.
    $entities = array();
    foreach ($comments as $comment) {
        $entity = get_entity($comment->entity_guid);
        // hic sunt dracones
        if (!$entity) {
            //continue;
            $entity = new ElggObject();
            $entity->setVolatileData('search_unavailable_entity', TRUE);
        }
        $comment_str = search_get_highlighted_relevant_substrings($comment->comment, $query);
        $comments_data = $entity->getVolatileData('search_comments_data');
        if (!$comments_data) {
            $comments_data = array();
        }
        $comments_data[] = array('annotation_id' => $comment->id, 'text' => $comment_str, 'owner_guid' => $comment->owner_guid, 'time_created' => $comment->time_created);
        $entity->setVolatileData('search_comments_data', $comments_data);
        $entities[] = $entity;
    }
    return array('entities' => $entities, 'count' => $count);
}
Esempio n. 3
0
/**
 * Get groups that match the search parameters.
 *
 * @param string $hook   Hook name
 * @param string $type   Hook type
 * @param array  $value  Empty array
 * @param array  $params Search parameters
 * @return array
 */
function group_subtypes_search_hook($hook, $type, $value, $params)
{
    $params['joins'] = (array) elgg_extract('joins', $params, array());
    $params['wheres'] = (array) elgg_extract('wheres', $params, array());
    $db_prefix = elgg_get_config('dbprefix');
    $query = sanitise_string($params['query']);
    $join = "JOIN {$db_prefix}groups_entity ge ON e.guid = ge.guid";
    array_unshift($params['joins'], $join);
    $fields = array('name', 'description');
    $where = search_get_where_sql('ge', $fields, $params);
    $params['wheres'][] = $where;
    $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;
    if (isset($params['sort']) || !isset($params['order_by'])) {
        $params['order_by'] = search_get_order_by_sql('e', 'ge', $params['sort'], $params['order']);
    }
    $entities = elgg_get_entities($params);
    // add the volatile data for why these entities have been returned.
    foreach ($entities as $entity) {
        $name = search_get_highlighted_relevant_substrings($entity->name, $query);
        $entity->setVolatileData('search_matched_title', $name);
        $description = search_get_highlighted_relevant_substrings($entity->description, $query);
        $entity->setVolatileData('search_matched_description', $description);
    }
    return array('entities' => $entities, 'count' => $count);
}
/**
 * Plugin project search hook
 * 
 * @param string $hook
 * @param string $type
 * @param <type> $value
 * @param <type> $params
 * @return array
 */
function plugins_search_hook($hook, $type, $value, $params)
{
    global $CONFIG;
    $query = sanitise_string($params['query']);
    $join = "JOIN {$CONFIG->dbprefix}objects_entity oe ON e.guid = oe.guid";
    $params['joins'] = array($join);
    $params['joins'][] = "JOIN {$CONFIG->dbprefix}metadata summary_md on e.guid = summary_md.entity_guid";
    $params['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings summary_msn on summary_md.name_id = summary_msn.id";
    $params['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings summary_msv on summary_md.value_id = summary_msv.id";
    $fields = array('title', 'description');
    $where = search_get_where_sql('oe', $fields, $params);
    // cheat and use LIKE for the summary field
    // this is kinda dirty.
    $likes = array();
    $query_arr = explode(' ', $query);
    foreach ($query_arr as $word) {
        $likes[] = "summary_msv.string LIKE \"%{$word}%\"";
    }
    $like_str = implode(' OR ', $likes);
    //$params['wheres'] = array("($where OR ($like_str))");
    $params['wheres'] = array($where);
    //	If metastrings were fulltext'd we could do this :(
    //	$select = "summary_msv.string summary_string";
    //	$params['selects'] = array($select);
    //
    //	$fields = array('string');
    //	$summary_where = search_get_where_sql('summary_msv', $fields, $params);
    //	$params['wheres'][] = $summary_where;
    if (($category = get_input('category')) && $category != 'all') {
        $params['metadata_name_value_pair'] = array('name' => 'plugincat', 'value' => $category, 'case_sensitive' => FALSE);
    }
    $params['order_by'] = search_get_order_by_sql('e', 'oe', $params['sort'], $params['order']);
    $entities = elgg_get_entities_from_metadata($params);
    $params['count'] = TRUE;
    $count = elgg_get_entities_from_metadata($params);
    // no need to continue if nothing here.
    if (!$count) {
        return array('entities' => array(), 'count' => $count);
    }
    // add the volatile data for why these entities have been returned.
    foreach ($entities as $entity) {
        $title = search_get_highlighted_relevant_substrings($entity->title, $params['query']);
        $entity->setVolatileData('search_matched_title', $title);
        $desc = search_get_highlighted_relevant_substrings($entity->summary, $params['query']);
        $entity->setVolatileData('search_matched_description', $desc);
    }
    return array('entities' => $entities, 'count' => $count);
}
Esempio n. 5
0
function members_extended_search($options = array())
{
    $db_prefix = elgg_get_config('dbprefix');
    $query = sanitise_string($options['query']);
    $options['joins'] = array("JOIN {$db_prefix}users_entity ue ON e.guid = ue.guid", "JOIN {$db_prefix}metadata md on e.guid = md.entity_guid", "JOIN {$db_prefix}metastrings msv ON n_table.value_id = msv.id");
    $r_where = "";
    $group_guid = $options['group_guid'];
    if ($group_guid) {
        $group = get_entity($group_guid);
        if (elgg_instanceof($group, 'group')) {
            elgg_set_page_owner_guid($group_guid);
            $options['joins'][] = "JOIN {$db_prefix}entity_relationships r ON e.guid = r.guid_one";
            $r_where = "AND (r.relationship = 'member' AND r.guid_two = '{$group_guid}')";
        }
    }
    // username and display name
    $fields = array('username', 'name');
    $where = search_get_where_sql('ue', $fields, $options, FALSE);
    // get the where clauses for the md names
    // can't use egef_metadata() because the n_table join comes too late.
    $clauses = _elgg_entities_get_metastrings_options('metadata', array('metadata_names' => $options['metadata_names']));
    $options['joins'] = array_merge($clauses['joins'], $options['joins']);
    // no fulltext index, can't disable fulltext search in this function.
    // $md_where .= " AND " . search_get_where_sql('msv', array('string'), $options, FALSE);
    $md_where = "(({$clauses['wheres'][0]}) AND msv.string LIKE '%{$query}%')";
    $options['wheres'] = array("(({$where}) OR ({$md_where}) {$r_where})");
    // override subtype -- All users should be returned regardless of subtype.
    $options['subtype'] = ELGG_ENTITIES_ANY_VALUE;
    $options['count'] = true;
    $count = elgg_get_entities($options);
    // no need to continue if nothing here.
    if (!$count) {
        return array('entities' => array(), 'count' => $count);
    }
    $options['count'] = FALSE;
    $options['order_by'] = search_get_order_by_sql('e', 'ue', $options['sort'], $options['order']);
    $entities = elgg_get_entities($options);
    return array('entities' => $entities, 'count' => $count);
}