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(0) {
33 my ( $self, $c ) = @_;
35 push @{$c->req->captures}, ('Info','Main');
37 $c->stash(template => 'wiki/page.tt2');
40 sub page : LocalRegex(^(?:([A-Z]\w*)(?::|%3A))?([A-Z]\w*)$) {
41 my ( $self, $c ) = @_;
44 $c->forward('findPage');
45 $c->acl_access_denied('test',$c->action,'No edit access for this page')
46 if defined $c->stash->{page}->{view} && !$c->stash->{page}->{view};
47 $c->forward('loadText');
49 unless ($c->stash->{page}->{wpid}){
50 $c->stash->{page}->{namespace} = $c->req->captures->[0];
51 $c->stash->{page}->{name} = $c->req->captures->[1];
52 $c->stash->{page}->{fullname} = ($c->stash->{page}->{namespace} ? $c->stash->{page}->{namespace}.':' : '')
53 . $c->stash->{page}->{name};
54 $c->stash->{page}->{post} = $dbh->selectrow_array(q{SELECT post
55 FROM wiki_namespace_access
56 WHERE namespace = COALESCE($1,'') AND post AND gid IN (SELECT groups($2))
57 },undef,$c->stash->{page}->{namespace}, $c->stash->{UID});
59 $c->stash(title => $c->stash->{page}->{fullname});
62 sub edit : LocalRegex(^edit/(?:([A-Z]\w*)(?::|%3A))?([A-Z]\w*)$) {
63 my ( $self, $c ) = @_;
66 $c->forward('findPage');
67 $c->acl_access_denied('test',$c->action,'No edit access for this page')
68 if defined $c->stash->{page}->{edit} && !$c->stash->{page}->{edit};
69 $c->forward('loadText');
70 $c->forward('findNamespaces');
72 unless ($c->stash->{page}->{wpid}){
73 $c->acl_access_denied('test',$c->action,'No edit access for this page')
74 unless @{$c->stash->{namespaces}};
75 $c->stash->{page}->{namespace} = $c->req->captures->[0];
76 $c->stash->{page}->{name} = $c->req->captures->[1];
80 sub history : LocalRegex(^history/(?:([A-Z]\w*)(?::|%3A))?([A-Z]\w*)$) {
81 my ( $self, $c ) = @_;
84 $c->forward('findPage');
86 my $query = $dbh->prepare(q{SELECT wprev,time,username,comment
87 FROM wiki_page_revisions JOIN users u USING (uid)
91 $query->execute($c->stash->{page}->{wpid});
92 $c->stash(revisions => $query->fetchall_arrayref({}) );
93 $c->stash(title => 'History for ' . $c->stash->{page}->{fullname});
96 sub postedit : Local {
97 my ( $self, $c, $p ) = @_;
103 my $wpid = $c->req->param('wpid');
104 if ( $wpid eq 'new'){
105 my $namespace = $dbh->selectrow_array(q{SELECT namespace
106 FROM wiki_namespace_access
107 WHERE namespace = $1 AND post AND gid IN (SELECT groups($2))
108 },undef,$c->req->param('namespace'), $c->stash->{UID});
110 my $query = $dbh->prepare(q{INSERT INTO wiki_pages (namespace,name) VALUES($1,$2) RETURNING wpid});
111 $query->execute($namespace,$c->req->param('name'));
112 $wpid = $query->fetchrow;
114 $c->forward('findPage',[$wpid]);
115 $c->acl_access_denied('test',$c->action,'No edit access for this page')
116 if defined $c->stash->{page}->{edit} && !$c->stash->{page}->{edit};
118 my $query = $dbh->prepare(q{INSERT INTO wiki_page_revisions
119 (wpid,parent,text,comment,uid) VALUES($1,$2,$3,$4,$5)
122 $c->req->params->{parent}||= undef;
123 $query->execute($wpid,$c->req->param('parent'),$c->req->param('text')
124 ,$c->req->param('comment'),$c->stash->{UID});
125 my $rev = $query->fetchrow;
126 $dbh->do(q{UPDATE wiki_pages SET wprev = $1 WHERE wpid = $2}
130 $c->res->redirect($c->uri_for($c->stash->{page}->{fullname}));
132 } if ($c->req->param('cmd') eq 'Submit');
135 if ($@ =~ /duplicate key value violates unique constraint "wiki_pages_namespace_key"/){
136 $c->stash(error => "Page does already exist");
137 }elsif ($@ =~ /value too long for type character varying\(255\)/){
138 $c->stash(error => 'The name is too long, keep it to max 255 characters');
140 $c->stash(error => $@);
145 $c->forward('findPage') if $p;
146 $c->forward('findNamespaces');
148 $c->stash->{page}->{namespace} = $c->req->param('namespace');
149 $c->stash->{page}->{name} = $c->req->param('name');
151 $c->stash(text => $c->req->param('text'));
152 $c->stash(template => 'wiki/edit.tt2');
155 sub findPage : Private {
156 my ( $self, $c, $p ) = @_;
159 my @arguments = ($c->stash->{UID});
162 $where = q{AND wpid = $2};
165 $where = q{AND (namespace = COALESCE($2,'') AND name = $3)};
166 push @arguments, @{$c->req->captures};
169 my $query = q{SELECT wpid,namespace,name,wprev
170 ,(CASE WHEN namespace <> '' THEN namespace || ':' ELSE '' END) || name AS fullname
171 ,bool_or(COALESCE(wpa.edit,wna.edit)) AS edit
172 ,bool_or(wna.post) AS post
173 ,bool_or(wpa.moderate OR wna.moderate) AS moderate
174 ,bool_or(wpa.wpid IS NOT NULL OR wna.namespace IS NOT NULL) AS view
176 LEFT OUTER JOIN (SELECT * FROM wiki_namespace_access
177 WHERE gid IN (SELECT groups($1))) wna USING (namespace)
178 LEFT OUTER JOIN (SELECT * FROM wiki_page_access
179 WHERE uid = $1) wpa USING (wpid)
181 } . $where . q{ GROUP BY wpid,namespace,name,wprev};
182 $query = $dbh->prepare($query);
183 $query->execute(@arguments);
185 my $page = $query->fetchrow_hashref;
186 $c->stash(page => $page);
189 sub loadText : Private {
190 my ( $self, $c, $p ) = @_;
193 my $text = $dbh->selectrow_array(q{SELECT text
194 FROM wiki_page_revisions WHERE wprev = $1
195 },undef,$c->stash->{page}->{wprev});
196 $c->stash(text => $text);
199 sub findNamespaces : Private {
200 my ( $self, $c, $p ) = @_;
203 my $query = $dbh->prepare(q{SELECT namespace FROM wiki_namespaces
204 WHERE namespace IN (SELECT namespace FROM wiki_namespace_access WHERE post AND gid IN (SELECT groups($1)))
207 $query->execute($c->stash->{UID});
208 $c->stash(namespaces => $query->fetchall_arrayref({}) );
214 Michael Andreen (harv@ruin.nu)