X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/4663f364bbc220bbdbf03582765b6d82f0bddc46..49eabc676a170bfbd31ee51c27e02c20355554dc:/IkiWiki/Plugin/comments.pm diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index 8122f9d51..01ee481f5 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -18,6 +18,7 @@ sub import { #{{{ hook(type => "preprocess", id => 'comments', call => \&preprocess); hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi); hook(type => "htmlize", id => "_comment", call => \&htmlize); + hook(type => "pagetemplate", id => "comments", call => \&pagetemplate); IkiWiki::loadplugin("inline"); IkiWiki::loadplugin("mdwn"); } # }}} @@ -32,23 +33,66 @@ sub getsetup () { #{{{ return plugin => { safe => 1, + rebuild => 1, + }, + # Pages where comments are shown, but new comments are not + # allowed, will show "Comments are closed". + comments_shown_pagespec => { + type => 'pagespec', + example => 'blog/*', + default => '', + description => 'PageSpec for pages where comments will be shown inline', + link => 'ikiwiki/PageSpec', + safe => 1, + rebuild => 1, + }, + comments_open_pagespec => { + type => 'pagespec', + example => 'blog/* and created_after(close_old_comments)', + default => '', + description => 'PageSpec for pages where new comments can be posted', + link => 'ikiwiki/PageSpec', + safe => 1, + rebuild => 1, + }, + comments_pagename => { + type => 'string', + example => 'comment_', + default => 'comment_', + description => 'Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12"', + safe => 0, # manual page moving will required rebuild => undef, }, + comments_allowdirectives => { + type => 'boolean', + default => 0, + example => 0, + description => 'Allow directives in newly posted comments?', + safe => 1, + rebuild => 0, + }, + comments_commit => { + type => 'boolean', + example => 1, + default => 1, + description => 'commit comments to the VCS', + # old uncommitted comments are likely to cause + # confusion if this is changed + safe => 0, + rebuild => 0, + }, } #}}} # Somewhat based on IkiWiki::Plugin::inline blog posting support sub preprocess (@) { #{{{ my %params=@_; - unless (length $config{cgiurl}) { - error(gettext("[[!comments plugin requires CGI enabled]]")); - } + return ""; my $page = $params{page}; $pagestate{$page}{comments}{comments} = defined $params{closed} ? (not IkiWiki::yesno($params{closed})) : 1; - $pagestate{$page}{comments}{allowhtml} = IkiWiki::yesno($params{allowhtml}); $pagestate{$page}{comments}{allowdirectives} = IkiWiki::yesno($params{allowdirectives}); $pagestate{$page}{comments}{commit} = defined $params{commit} ? IkiWiki::yesno($params{commit}) @@ -70,8 +114,8 @@ sub preprocess (@) { #{{{ debug("page $params{page} => destpage $params{destpage}"); - my $posts = ''; unless (defined $params{inline} && !IkiWiki::yesno($params{inline})) { + my $posts = ''; eval q{use IkiWiki::Plugin::inline}; error($@) if ($@); my @args = ( @@ -90,10 +134,11 @@ sub preprocess (@) { #{{{ push @args, feedshow => $params{feedshow} if defined $params{feedshow}; push @args, timeformat => $params{timeformat} if defined $params{timeformat}; push @args, feedonly => $params{feedonly} if defined $params{feedonly}; - $posts = "\n" . IkiWiki::preprocess_inline(@args); + $posts = IkiWiki::preprocess_inline(@args); + $formtemplate->param("comments" => $posts); } - return $formtemplate->output . $posts; + return $formtemplate->output; } # }}} # FIXME: logic taken from editpage, should be common code? @@ -106,6 +151,7 @@ sub getcgiuser ($) { # {{{ } # }}} # FIXME: logic adapted from recentchanges, should be common code? +# returns (author URL, pretty-printed version) sub linkuser ($) { # {{{ my $user = shift; my $oiduser = eval { IkiWiki::openiduser($user) }; @@ -121,18 +167,6 @@ sub linkuser ($) { # {{{ } } # }}} -# FIXME: taken from IkiWiki::Plugin::editpage, should be common? -sub checksessionexpiry ($$) { # {{{ - my $session = shift; - my $sid = shift; - - if (defined $session->param("name")) { - if (! defined $sid || $sid ne $session->id) { - error(gettext("Your login session has expired.")); - } - } -} # }}} - # Mostly cargo-culted from IkiWiki::plugin::editpage sub sessioncgi ($$) { #{{{ my $cgi=shift; @@ -186,11 +220,9 @@ sub sessioncgi ($$) { #{{{ error(gettext("bad page name")); } - my $allow_directives = $pagestate{$page}{comments}{allowdirectives}; - my $allow_html = $pagestate{$page}{comments}{allowdirectives}; - my $commit_comments = defined $pagestate{$page}{comments}{commit} - ? $pagestate{$page}{comments}{commit} - : 1; + my $allow_directives = $config{comments_allowdirectives}; + my $commit_comments = $config{comments_commit}; + my $comments_pagename = $config{comments_pagename}; # FIXME: is this right? Or should we be using the candidate subpage # (whatever that might mean) as the base URL? @@ -203,27 +235,29 @@ sub sessioncgi ($$) { #{{{ htmllink($page, $page, 'ikiwiki/formatting', noimageinline => 1, linktext => 'FormattingHelp'), - allowhtml => $allow_html, allowdirectives => $allow_directives); + if ($form->submitted eq CANCEL) { + # bounce back to the page they wanted to comment on, and exit. + # CANCEL need not be considered in future + IkiWiki::redirect($cgi, urlto($page, undef, 1)); + exit; + } + if (not exists $pagesources{$page}) { error(sprintf(gettext( "page '%s' doesn't exist, so you can't comment"), $page)); } - if (not $pagestate{$page}{comments}{comments}) { + + if (not pagespec_match($page, $config{comments_open_pagespec}, + location => $page)) { error(sprintf(gettext( - "comments are not enabled on page '%s'"), + "comments on page '%s' are closed"), $page)); } - if ($form->submitted eq CANCEL) { - # bounce back to the page they wanted to comment on, and exit. - # CANCEL need not be considered in future - IkiWiki::redirect($cgi, urlto($page, undef, 1)); - exit; - } - + IkiWiki::checksessionexpiry($session, $cgi->param('sid')); IkiWiki::check_canedit($page . "[postcomment]", $cgi, $session); my ($authorurl, $author) = linkuser(getcgiuser($session)); @@ -235,27 +269,32 @@ sub sessioncgi ($$) { #{{{ unless ($allow_directives) { # don't allow new-style directives at all - $body =~ s/(^|[^\\])\[\[!/$1\\[[!/g; + $body =~ s/(^|[^\\])\[\[!/$1[[!/g; # don't allow [[ unless it begins an old-style # wikilink, if prefix_directives is off - $body =~ s/(^|[^\\])\[\[(?![^\n\s\]+]\]\])/$1\\[[!/g + $body =~ s/(^|[^\\])\[\[(?![^\n\s\]+]\]\])/$1[[!/g unless $config{prefix_directives}; } - unless ($allow_html) { - $body =~ s/&(\w|#)/&$1/g; - $body =~ s//>/g; - } + # FIXME: check that the wiki is locked right now, because + # if it's not, there are mad race conditions! + + # FIXME: rather a simplistic way to make the comments... + my $i = 0; + my $file; + my $location; + do { + $i++; + $location = "$page/${comments_pagename}${i}"; + } while (-e "$config{srcdir}/$location._comment"); + + my $anchor = "${comments_pagename}${i}"; IkiWiki::run_hooks(sanitize => sub { - # $fake is a possible location for this comment. We don't - # know yet what the comment number *actually* is. - my $fake = "$page/_comment_1"; $body=shift->( - page => $fake, - destpage => $fake, + page => $location, + destpage => $location, content => $body, ); }); @@ -268,6 +307,8 @@ sub sessioncgi ($$) { #{{{ $content_tmpl->param(authorurl => $authorurl); $content_tmpl->param(subject => $form->field('subject')); $content_tmpl->param(body => $body); + $content_tmpl->param(anchor => "$anchor"); + $content_tmpl->param(permalink => "$baseurl#$anchor"); my $content = $content_tmpl->output; @@ -278,14 +319,11 @@ sub sessioncgi ($$) { #{{{ # - this means that if they do, rocks fall and everyone dies if ($form->submitted eq PREVIEW) { - # $fake is a possible location for this comment. We don't - # know yet what the comment number *actually* is. - my $fake = "$page/_comment_1"; - my $preview = IkiWiki::htmlize($fake, $page, 'mdwn', + my $preview = IkiWiki::htmlize($location, $page, 'mdwn', IkiWiki::linkify($page, $page, IkiWiki::preprocess($page, $page, - IkiWiki::filter($fake, $page, - $content), + IkiWiki::filter($location, + $page, $content), 0, 1))); IkiWiki::run_hooks(format => sub { $preview = shift->(page => $page, @@ -306,24 +344,10 @@ sub sessioncgi ($$) { #{{{ } if ($form->submitted eq POST_COMMENT && $form->validate) { - # Let's get posting. We don't check_canedit here because - # that somewhat defeats the point of this plugin. - - checksessionexpiry($session, $cgi->param('sid')); - - # FIXME: check that the wiki is locked right now, because - # if it's not, there are mad race conditions! - - # FIXME: rather a simplistic way to make the comments... - my $i = 0; - my $file; - do { - $i++; - $file = "$page/_comment_${i}._comment"; - } while (-e "$config{srcdir}/$file"); + my $file = "$location._comment"; # FIXME: could probably do some sort of graceful retry - # if I could be bothered + # on error? Would require significant unwinding though writefile($file, $config{srcdir}, $content); my $conflict; @@ -332,7 +356,9 @@ sub sessioncgi ($$) { #{{{ my $message = gettext("Added a comment"); if (defined $form->field('subject') && length $form->field('subject')) { - $message .= ": ".$form->field('subject'); + $message = sprintf( + gettext("Added a comment: %s"), + $form->field('subject')); } IkiWiki::rcs_add($file); @@ -353,7 +379,7 @@ sub sessioncgi ($$) { #{{{ error($conflict) if defined $conflict; # Bounce back to where we were, but defeat broken caches - my $anticache = "?updated=$page/_comment_$i"; + my $anticache = "?updated=$page/${comments_pagename}${i}"; IkiWiki::redirect($cgi, urlto($page, undef, 1).$anticache); } else { @@ -364,6 +390,21 @@ sub sessioncgi ($$) { #{{{ exit; } #}}} +sub pagetemplate (@) { #{{{ + my %params = @_; + + my $page = $params{page}; + my $template = $params{template}; + + if ($template->query(name => 'comments')) { + my $comments = undef; + + if (defined $comments && length $comments) { + $template->param(name => $comments); + } + } +} # }}} + package IkiWiki::PageSpec; sub match_postcomment ($$;@) {