public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
// No keywords? No posts
if (!$this->search_query) {
return false;
}
// generate a search_key from all the options to identify the results
$search_key = md5(implode('#', array(implode(', ', $this->split_words), $type, $fields, $terms, $sort_days, $sort_key, $topic_id, implode(',', $ex_fid_ary), $post_visibility, implode(',', $author_ary))));
if ($start < 0) {
$start = 0;
}
// try reading the results from cache
$result_count = 0;
if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) {
return $result_count;
}
$id_ary = array();
$join_topic = $type == 'posts' ? false : true;
// Build sql strings for sorting
$sql_sort = $sort_by_sql[$sort_key] . ($sort_dir == 'a' ? ' ASC' : ' DESC');
$sql_sort_table = $sql_sort_join = '';
switch ($sql_sort[0]) {
case 'u':
$sql_sort_table = USERS_TABLE . ' u, ';
$sql_sort_join = $type == 'posts' ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ';
break;
case 't':
$join_topic = true;
break;
case 'f':
$sql_sort_table = FORUMS_TABLE . ' f, ';
$sql_sort_join = ' AND f.forum_id = p.forum_id ';
break;
}
// Build some display specific sql strings
switch ($fields) {
case 'titleonly':
$sql_match = 'p.post_subject';
$sql_match_where = ' AND p.post_id = t.topic_first_post_id';
$join_topic = true;
break;
case 'msgonly':
$sql_match = 'p.post_text';
$sql_match_where = '';
break;
case 'firstpost':
$sql_match = 'p.post_subject, p.post_text';
$sql_match_where = ' AND p.post_id = t.topic_first_post_id';
$join_topic = true;
break;
default:
$sql_match = 'p.post_subject, p.post_text';
$sql_match_where = '';
break;
}
$sql_select = !$result_count ? 'SQL_CALC_FOUND_ROWS ' : '';
$sql_select = $type == 'posts' ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';
$sql_from = $join_topic ? TOPICS_TABLE . ' t, ' : '';
$field = $type == 'posts' ? 'post_id' : 'topic_id';
if (sizeof($author_ary) && $author_name) {
// first one matches post of registered users, second one guests and deleted users
$sql_author = ' AND (' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
} else {
if (sizeof($author_ary)) {
$sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary);
} else {
$sql_author = '';
}
}
$sql_where_options = $sql_sort_join;
$sql_where_options .= $topic_id ? ' AND p.topic_id = ' . $topic_id : '';
$sql_where_options .= $join_topic ? ' AND t.topic_id = p.topic_id' : '';
$sql_where_options .= sizeof($ex_fid_ary) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= ' AND ' . $post_visibility;
$sql_where_options .= $sql_author;
$sql_where_options .= $sort_days ? ' AND p.post_time >= ' . (time() - $sort_days * 86400) : '';
$sql_where_options .= $sql_match_where;
$sql = "SELECT {$sql_select}\n\t\t\tFROM {$sql_from}{$sql_sort_table}" . POSTS_TABLE . " p\n\t\t\tWHERE MATCH ({$sql_match}) AGAINST ('" . $this->db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE)\n\t\t\t\t{$sql_where_options}\n\t\t\tORDER BY {$sql_sort}";
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $this->db->sql_fetchrow($result)) {
$id_ary[] = (int) $row[$field];
}
$this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
// if the total result count is not cached yet, retrieve it from the db
if (!$result_count) {
$sql_found_rows = 'SELECT FOUND_ROWS() as result_count';
$result = $this->db->sql_query($sql_found_rows);
$result_count = (int) $this->db->sql_fetchfield('result_count');
$this->db->sql_freeresult($result);
if (!$result_count) {
return false;
}
}
if ($start >= $result_count) {
$start = floor(($result_count - 1) / $per_page) * $per_page;
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $this->db->sql_fetchrow($result)) {
$id_ary[] = (int) $row[$field];
}
$this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
}
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, (int) $per_page);
return $result_count;
}