1 package NDWeb::Controller::Wiki;
5 use parent 'Catalyst::Controller';
7 use Text::MediawikiFormat prefix => '/wiki/';
11 NDWeb::Controller::Wiki - Catalyst Controller
27 my ( $self, $c ) = @_;
29 $c->stash(wikiformat => \&wikiformat);
32 sub index :Path :Args(1) {
33 my ( $self, $c, $page ) = @_;
35 $c->forward('page',$page);
36 $c->stash(template => 'wiki/page.tt2');
39 sub main :Path :Args(0) {
40 my ( $self, $c ) = @_;
42 $c->forward('page', ['Info:Main']);
43 $c->stash(template => 'wiki/page.tt2');
47 my ( $self, $c, $p ) = @_;
50 $c->forward('findPage');
51 $c->acl_access_denied('test',$c->action,'No edit access for this page')
52 if defined $c->stash->{page}->{view} && !$c->stash->{page}->{view};
53 $c->forward('loadText');
55 unless ($c->stash->{page}->{wpid}){
56 $c->stash->{page}->{namespace} = $c->stash->{namespace};
57 $c->stash->{page}->{name} = $c->stash->{name};
58 $c->stash->{page}->{fullname} = ($c->stash->{page}->{namespace} ? $c->stash->{page}->{namespace}.':' : '')
59 . $c->stash->{page}->{name};
60 $c->stash->{page}->{post} = $dbh->selectrow_array(q{SELECT post
61 FROM wiki_namespace_access
62 WHERE namespace = COALESCE($1,'') AND post AND gid IN (SELECT groups($2))
63 },undef,$c->stash->{page}->{namespace}, $c->stash->{UID});
65 $c->stash(title => $c->stash->{page}->{fullname});
68 sub edit :Local :Args(1) {
69 my ( $self, $c, @p ) = @_;
72 $c->forward('findPage');
73 $c->acl_access_denied('test',$c->action,'No edit access for this page')
74 if defined $c->stash->{page}->{edit} && !$c->stash->{page}->{edit};
75 $c->forward('loadText');
76 $c->forward('findNamespaces');
78 unless ($c->stash->{page}->{wpid}){
79 $c->acl_access_denied('test',$c->action,'No edit access for this page')
80 unless @{$c->stash->{namespaces}};
81 $c->stash->{page}->{namespace} = $c->stash->{namespace};
82 $c->stash->{page}->{name} = $c->stash->{name};
86 sub history :Local :Args(1) {
87 my ( $self, $c ) = @_;
90 $c->forward('findPage');
92 my $query = $dbh->prepare(q{SELECT wprev,time,username,comment
93 FROM wiki_page_revisions JOIN users u USING (uid)
97 $query->execute($c->stash->{page}->{wpid});
98 $c->stash(revisions => $query->fetchall_arrayref({}) );
99 $c->stash(title => 'History for ' . $c->stash->{page}->{fullname});
102 sub postedit : Local {
103 my ( $self, $c, $p ) = @_;
106 my $ns = $c->req->param('namespace');
107 my $name = $c->req->param('name');
108 my $text = $c->req->param('text');
112 my $wpid = $c->req->param('wpid');
113 if ( $wpid eq 'new'){
114 unless ($c->req->param('name') =~ /^([A-Z]\w*)$/){
115 die 'The name is not valid, start with a capital letter and only use alphanumerical characters or _ for the rest';
117 my $namespace = $dbh->selectrow_array(q{SELECT namespace
118 FROM wiki_namespace_access
119 WHERE namespace = $1 AND post AND gid IN (SELECT groups($2))
120 },undef,$ns, $c->stash->{UID});
122 my $query = $dbh->prepare(q{INSERT INTO wiki_pages (namespace,name) VALUES($1,$2) RETURNING wpid});
123 $query->execute($namespace,$name);
124 $wpid = $query->fetchrow;
126 $c->forward('findPage',[$wpid]);
127 $c->acl_access_denied('test',$c->action,'No edit access for this page')
128 if defined $c->stash->{page}->{edit} && !$c->stash->{page}->{edit};
130 my $query = $dbh->prepare(q{INSERT INTO wiki_page_revisions
131 (wpid,parent,text,comment,uid) VALUES($1,$2,$3,$4,$5)
134 $c->req->params->{parent}||= undef;
135 my $parent = $c->req->param('parent');
136 my $comment = $c->req->param('comment');
137 $query->execute($wpid,$parent,$text
138 ,$comment,$c->stash->{UID});
139 my $rev = $query->fetchrow;
140 $dbh->do(q{UPDATE wiki_pages SET wprev = $1 WHERE wpid = $2}
144 $c->res->redirect($c->uri_for($c->stash->{page}->{fullname}));
146 } if ($c->req->param('cmd') eq 'Submit');
149 if ($@ =~ /duplicate key value violates unique constraint "wiki_pages_namespace_key"/){
150 $c->stash(error => "Page does already exist");
151 }elsif ($@ =~ /value too long for type character varying\(255\)/){
152 $c->stash(error => 'The name is too long, keep it to max 255 characters');
154 $c->stash(error => $@);
159 $c->forward('findPage') if $p;
160 $c->forward('findNamespaces');
162 $c->stash->{page}->{namespace} = $ns;
163 $c->stash->{page}->{name} = $name;
165 $c->stash(text => $text);
166 $c->stash(template => 'wiki/edit.tt2');
170 my ( $self, $c ) = @_;
173 if ($c->req->param('search')){
174 $c->stash(search => $c->req->param('search'));
175 my $queryfunc = 'plainto_tsquery';
176 $queryfunc = 'to_tsquery' if $c->req->param('advsearch');
177 my $posts = $dbh->prepare(q{SELECT wp.wpid,namespace,name
178 ,(CASE WHEN namespace <> '' THEN namespace || ':' ELSE '' END) || name AS fullname
179 ,ts_headline(wpr.text,}.$queryfunc.q{($2)) AS headline
180 ,ts_rank_cd(textsearch, }.$queryfunc.q{($2),32) AS rank
182 JOIN wiki_page_revisions wpr USING (wprev)
183 WHERE (namespace IN (SELECT namespace FROM wiki_namespace_access WHERE gid IN (SELECT groups($1)))
184 OR wp.wpid IN (SELECT wpid FROM wiki_page_access WHERE uid = $1))
185 AND textsearch @@ }.$queryfunc.q{($2)
189 my $search = $c->req->param('search');
190 $posts->execute($c->stash->{UID},$search);
192 while (my $post = $posts->fetchrow_hashref){
195 $c->stash(searchresults => \@posts);
198 $c->stash( searcherror => $dbh->errstr);
204 sub findPage : Private {
205 my ( $self, $c, $p ) = @_;
208 my @arguments = ($c->stash->{UID});
211 $where = q{AND wpid = $2};
213 } elsif ($p =~ /^(?:([A-Z]\w*):)?([A-Z]\w*)$/){
214 $where = q{AND (namespace = COALESCE($2,'') AND name = $3)};
215 push @arguments, $1, $2;
216 $c->stash(namespace => $1);
217 $c->stash(name => $2);
219 $c->detach('/default');
222 my $query = q{SELECT wpid,namespace,name,wprev
223 ,(CASE WHEN namespace <> '' THEN namespace || ':' ELSE '' END) || name AS fullname
224 ,bool_or(COALESCE(wpa.edit,wna.edit)) AS edit
225 ,bool_or(wna.post) AS post
226 ,bool_or(wpa.moderate OR wna.moderate) AS moderate
227 ,bool_or(wpa.wpid IS NOT NULL OR wna.namespace IS NOT NULL) AS view
229 LEFT OUTER JOIN (SELECT * FROM wiki_namespace_access
230 WHERE gid IN (SELECT groups($1))) wna USING (namespace)
231 LEFT OUTER JOIN (SELECT * FROM wiki_page_access
232 WHERE uid = $1) wpa USING (wpid)
234 } . $where . q{ GROUP BY wpid,namespace,name,wprev};
235 $query = $dbh->prepare($query);
236 $query->execute(@arguments);
238 my $page = $query->fetchrow_hashref;
239 $c->stash(page => $page);
242 sub loadText : Private {
243 my ( $self, $c, $p ) = @_;
246 my $text = $dbh->selectrow_array(q{SELECT text
247 FROM wiki_page_revisions WHERE wprev = $1
248 },undef,$c->stash->{page}->{wprev});
249 $c->stash(text => $text);
252 sub findNamespaces : Private {
253 my ( $self, $c, $p ) = @_;
256 my $query = $dbh->prepare(q{SELECT namespace FROM wiki_namespaces
257 WHERE namespace IN (SELECT namespace FROM wiki_namespace_access WHERE post AND gid IN (SELECT groups($1)))
260 $query->execute($c->stash->{UID});
261 $c->stash(namespaces => $query->fetchall_arrayref({}) );
267 Michael Andreen (harv@ruin.nu)