sub parse {
my $self = shift;
if ($self->{URI} =~ m{^/.*/allUnread}){
- param('allUnread',1);
+ $self->{allUnread} = 1;
+ }elsif ($self->{URI} =~ m{^/.*/search(?:/(.*))?}){
+ bless $self, 'NDWeb::Pages::Forum::Search';
+ $self->{PAGE} = 'forum/search';
}
}
,undef,$thread->{fcid}) or $ND::ERROR .= p($DBH->errstr);
$BODY->param(Category => $category);
- }elsif(defined param('allUnread')){ #List threads in this board
+ }elsif(defined $self->{allUnread}){ #List threads in this board
$BODY->param(AllUnread => 1);
$BODY->param(Id => $board->{id});
my ($time) = $DBH->selectrow_array('SELECT now()::timestamp',undef);
my ($category) = $DBH->selectrow_array(q{SELECT category FROM forum_categories WHERE fcid = $1}
,undef,$board->{fcid}) or $ND::ERROR .= p($DBH->errstr);
$BODY->param(Category => $category);
-
- }elsif($self->{URI} =~ m{^/.*/search/(.*)}){ #List threads in this board
}else{ #List boards
$BODY->param(Overview => 1);
$categories->execute or $ND::ERROR .= p($DBH->errstr);
--- /dev/null
+#**************************************************************************
+# Copyright (C) 2006 by Michael Andreen <harvATruinDOTnu> *
+# *
+# This program is free software; you can redistribute it and/or modify *
+# it under the terms of the GNU General Public License as published by *
+# the Free Software Foundation; either version 2 of the License, or *
+# (at your option) any later version. *
+# *
+# This program is distributed in the hope that it will be useful, *
+# but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# GNU General Public License for more details. *
+# *
+# You should have received a copy of the GNU General Public License *
+# along with this program; if not, write to the *
+# Free Software Foundation, Inc., *
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+#**************************************************************************/
+
+package NDWeb::Pages::Forum::Search;
+use strict;
+use warnings;
+use NDWeb::Forum;
+use CGI qw/:standard/;
+use NDWeb::Include;
+use ND::Include;
+
+use base qw/NDWeb::Pages::Forum/;
+
+sub render_body {
+ my $self = shift;
+ my ($BODY) = @_;
+ my $DBH = $self->{DBH};
+ $self->{TITLE} = 'Forum';
+
+ if (param('search')){
+ my $posts = $DBH->prepare(q{SELECT fp.ftid,u.username,ft.subject
+ ,ts_headline(fp.message,to_tsquery($2)) AS headline
+ ,ts_rank_cd(fp.textsearch, to_tsquery($2),32) AS rank
+ FROM forum_boards fb
+ JOIN forum_threads ft USING (fbid)
+ JOIN forum_posts fp USING (ftid)
+ JOIN users u ON fp.uid = u.uid
+ WHERE fb.fbid IN (SELECT fbid FROM forum_access
+ WHERE gid IN (SELECT groups($1)))
+ AND fp.textsearch @@@ to_tsquery($2)
+ ORDER BY rank DESC
+ }) or warn $DBH->errstr;
+ $posts->execute($ND::UID,param('search')) or warn $DBH->errstr;
+ my @posts;
+ while (my $post = $posts->fetchrow_hashref){
+ push @posts,$post;
+ }
+ $BODY->param(SearchResult => \@posts);
+ }
+ return $BODY;
+}
+
+1;
--- /dev/null
+ALTER TABLE forum_posts ADD textsearch tsvector;
+
+UPDATE forum_posts fp SET textsearch = setweight(to_tsvector(coalesce(ft.subject,'')), 'A') || setweight(to_tsvector(coalesce(u.username,'')), 'B') || setweight(to_tsvector(coalesce(fp.message,'')), 'D') FROM forum_threads ft, users u WHERE fp.ftid = ft.ftid AND u.uid = fp.uid;
+
+CREATE INDEX forum_posts_textsearch_index ON forum_posts USING gin(textsearch);
+
+/*CREATE OR REPLACE FUNCTION update_forum_post() RETURNS "trigger"
+AS $_X$
+ my $query = spi_prepare(q{UPDATE forum_posts fp
+ SET textsearch = setweight(to_tsvector(coalesce(ft.subject,'')), 'A')
+ || setweight(to_tsvector(coalesce(u.username,'')), 'B')
+ || setweight(to_tsvector(coalesce(fp.message,'')), 'D')
+ FROM forum_threads ft, users u
+ WHERE fp.ftid = ft.ftid AND u.uid = fp.uid AND fp.fpid = $1},'int4');
+ spi_exec_prepared($query,$_TD->{new}{fpid});
+ spi_freeplan($query);
+$_X$
+ LANGUAGE plperl;
+*/
+CREATE OR REPLACE FUNCTION update_forum_post() RETURNS "trigger"
+AS $_X$
+DECLARE
+ rec RECORD;
+BEGIN
+ SELECT setweight(to_tsvector(coalesce(ft.subject,'')), 'A')
+ || setweight(to_tsvector(coalesce(u.username,'')), 'B') AS ts
+ INTO STRICT rec
+ FROM forum_threads ft, users u
+ WHERE NEW.ftid = ft.ftid AND u.uid = NEW.uid;
+ NEW.textsearch := rec.ts
+ || setweight(to_tsvector(coalesce(NEW.message,'')), 'D');
+ return NEW;
+END;
+$_X$
+ LANGUAGE plpgsql;
+
+CREATE TRIGGER update_forum_post
+ BEFORE INSERT OR UPDATE ON forum_posts
+ FOR EACH ROW
+ EXECUTE PROCEDURE update_forum_post();
use NDWeb::Pages::PlanetNaps;
use NDWeb::Pages::Motd;
use NDWeb::Pages::Forum;
+use NDWeb::Pages::Forum::Search;
use NDWeb::Pages::Settings;
use NDWeb::Pages::Graph;
use NDWeb::Pages::Mail;
--- /dev/null
+<form action="/<TMPL_VAR NAME=PAGE>" method="post"><fieldset class="forum-post"> <legend>Search</legend>
+ Use | (OR) or & (AND) to separate words. Word:A searches for Word in
+ topic and Word:B searches for Word as author. 'Two words' to search for a
+ longer string. Word:D limits the search to just the message body.
+ <p>Search query: <input type="text" name="search" value=""/></p>
+ <input type="submit" name="cmd" value="Search"/>
+</fieldset></form>
+
+<TMPL_IF SearchResult>
+<table>
+<tr>
+ <th>Thread</th>
+ <th>Author</th>
+ <th>Message</th>
+ <th>Rank</th>
+</tr>
+<TMPL_LOOP SearchResult>
+ <tr align="left" class="<TMPL_IF __odd__>odd<TMPL_ELSE>even</TMPL_IF>">
+ <td><a href="/forum?t=<TMPL_VAR NAME=FTID>"> <TMPL_VAR ESCAPE=NONE NAME=Subject> </a></td>
+ <td><TMPL_VAR NAME=Username></td>
+ <td align="center"><TMPL_VAR ESCAPE=NONE NAME=Headline></td>
+ <td><TMPL_VAR NAME=Rank></td>
+ </tr>
+</TMPL_LOOP>
+</table>
+</TMPL_IF>
<li><a href="/settings">Settings</a></li>
<li><a href="/forum">Forum</a></li>
<li><a href="/forum/allUnread">New posts <TMPL_IF UnreadPosts>(<span class="<TMPL_IF NewPosts>newposts<TMPL_ELSE>unreadposts</TMPL_IF>"><TMPL_VAR NAME=UnreadPosts></span>)</TMPL_IF></a></li>
+ <li><a href="/forum/search">Forum search</a></li>
</ul> <p>Tick: <TMPL_VAR NAME=TICK></p>
<TMPL_IF isMEMBER>
<p>Member menu</p>