From d9d910f6765de6ba07508ab56a5a0f93edb4c8ad Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 6 May 2010 19:19:51 -0400 Subject: moved comments pending moderation * comments: Comments pending moderation are now stored in the srcdir alongside accepted comments, but with a `._comment_pending` extension. * This allows easier byhand moderation, as the "_pending" need only be stripped off and the comment be committed to version control. * The `comment_pending()` pagespec can be used to match such unmoderated comments, which makes it easy to add a feed of them, or a counter indicating how many there are. * Belatedly added a `comment()` pagespec. --- IkiWiki.pm | 4 +- IkiWiki/Plugin/comments.pm | 130 +++++++++++++++++++++++++++++++------------- debian/NEWS | 6 ++ debian/changelog | 8 +++ doc/ikiwiki/pagespec.mdwn | 2 + doc/plugins/comments.mdwn | 4 +- doc/tips/comments_feed.mdwn | 9 ++- ikiwiki.spec | 2 +- 8 files changed, 121 insertions(+), 44 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 43995fc96..11cfcdfd2 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2342,12 +2342,12 @@ sub match_glob ($$;@) { } sub match_internal ($$;@) { - return match_glob($_[0], $_[1], @_, internal => 1) + return match_glob(shift, shift, @_, internal => 1) } sub match_page ($$;@) { my $page=shift; - my $match=match_glob($page, $_[1], @_); + my $match=match_glob($page, shift, @_); if ($match && ! defined IkiWiki::pagetype($IkiWiki::pagesources{$page})) { return IkiWiki::FailReason->new("$page is not a page"); } diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index 89560c88b..448ef02f7 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -26,8 +26,11 @@ sub import { hook(type => "preprocess", id => '_comment', call => \&preprocess); hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi); hook(type => "htmlize", id => "_comment", call => \&htmlize); + hook(type => "htmlize", id => "_comment_pending", + call => \&htmlize_pending); hook(type => "pagetemplate", id => "comments", call => \&pagetemplate); - hook(type => "formbuilder_setup", id => "comments", call => \&formbuilder_setup); + hook(type => "formbuilder_setup", id => "comments", + call => \&formbuilder_setup); # Load goto to fix up user page links for logged-in commenters IkiWiki::loadplugin("goto"); IkiWiki::loadplugin("inline"); @@ -104,6 +107,14 @@ sub htmlize { return $params{content}; } +sub htmlize_pending { + my %params = @_; + return sprintf(gettext("comment pending %s"), + ''. + gettext("moderation").''); +} + # FIXME: copied verbatim from meta sub safeurl ($) { my $url=shift; @@ -462,9 +473,15 @@ sub editcomment ($$) { $postcomment=0; if (! $ok) { - my $penddir=$config{wikistatedir}."/comments_pending"; - $location=unique_comment_location($page, $content, $penddir); - writefile("$location._comment", $penddir, $content); + $location=unique_comment_location($page, $content, $config{srcdir}); + writefile("$location._comment_pending", $config{srcdir}, $content); + + # Refresh so anything that deals with pending + # comments can be updated. + require IkiWiki::Render; + IkiWiki::refresh(); + IkiWiki::saveindex(); + IkiWiki::printheader($session); print IkiWiki::misctemplate(gettext(gettext("comment stored for moderation")), "

". @@ -540,21 +557,24 @@ sub commentmoderation ($$) { my %vars=$cgi->Vars; my $added=0; foreach my $id (keys %vars) { - if ($id =~ /(.*)\Q._comment\E$/) { + if ($id =~ /(.*)\Q._comment(?:_pending)?\E$/) { my $action=$cgi->param($id); next if $action eq 'Defer' && ! $rejectalldefer; # Make sure that the id is of a legal - # pending comment before untainting. - my ($f)= $id =~ /$config{wiki_file_regexp}/; + # pending comment. + my ($f) = $id =~ /$config{wiki_file_regexp}/; if (! defined $f || ! length $f || IkiWiki::file_pruned($f)) { error("illegal file"); } - my $page=IkiWiki::possibly_foolish_untaint(IkiWiki::dirname($1)); - my $file="$config{wikistatedir}/comments_pending/". - IkiWiki::possibly_foolish_untaint($id); + my $page=IkiWiki::dirname($f); + my $file="$config{srcdir}/$f"; + if (! -e $file) { + # old location + $file="$config{wikistatedir}/comments_pending/".$f; + } if ($action eq 'Accept') { my $content=eval { readfile($file) }; @@ -567,9 +587,6 @@ sub commentmoderation ($$) { $added++; } - # This removes empty subdirs, so the - # .ikiwiki/comments_pending dir will - # go away when all are moderated. require IkiWiki::Render; IkiWiki::prune($file); } @@ -596,15 +613,14 @@ sub commentmoderation ($$) { } my @comments=map { - my ($id, $ctime)=@{$_}; - my $file="$config{wikistatedir}/comments_pending/$id"; - my $content=readfile($file); + my ($id, $dir, $ctime)=@{$_}; + my $content=readfile("$dir/$id"); my $preview=previewcomment($content, $id, - IkiWiki::dirname($_), $ctime); + $id, $ctime); { id => $id, view => $preview, - } + } } sort { $b->[1] <=> $a->[1] } comments_pending(); my $template=template("commentmoderation.tmpl"); @@ -635,26 +651,35 @@ sub formbuilder_setup (@) { } sub comments_pending () { - my $dir="$config{wikistatedir}/comments_pending/"; - return unless -d $dir; - my @ret; + eval q{use File::Find}; error($@) if $@; - find({ - no_chdir => 1, - wanted => sub { - my $file=decode_utf8($_); - $file=~s/^\Q$dir\E\/?//; - return if ! length $file || IkiWiki::file_pruned($file) - || -l $_ || -d _ || $file !~ /\Q._comment\E$/; - my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint - if (defined $f) { - my $ctime=(stat($_))[10]; - push @ret, [$f, $ctime]; + + my $find_comments=sub { + my $dir=shift; + my $extension=shift; + return unless -d $dir; + find({ + no_chdir => 1, + wanted => sub { + my $file=decode_utf8($_); + $file=~s/^\Q$dir\E\/?//; + return if ! length $file || IkiWiki::file_pruned($file) + || -l $_ || -d _ || $file !~ /\Q$extension\E$/; + my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint + if (defined $f) { + my $ctime=(stat($_))[10]; + push @ret, [$f, $dir, $ctime]; + } } - } - }, $dir); + }, $dir); + }; + + $find_comments->($config{srcdir}, "._comment_pending"); + # old location + $find_comments->("$config{wikistatedir}/comments_pending/", + "._comment"); return @ret; } @@ -689,7 +714,7 @@ sub previewcomment ($$$) { sub commentsshown ($) { my $page=shift; - return ! pagespec_match($page, "internal(*/$config{comments_pagename}*)", + return ! pagespec_match($page, "comment(*)", location => $page) && pagespec_match($page, $config{comments_pagespec}, location => $page); @@ -719,7 +744,7 @@ sub pagetemplate (@) { my $comments = undef; if ($shown) { $comments = IkiWiki::preprocess_inline( - pages => "internal($page/$config{comments_pagename}*)", + pages => "comment($page)", template => 'comment', show => 0, reverse => 'yes', @@ -847,7 +872,8 @@ sub unique_comment_location ($$$) { do { $i++; $location = "$page/$config{comments_pagename}${i}_${content_md5}"; - } while (-e "$dir/$location._comment"); + } while (-e "$dir/$location._comment" || + -e "$dir/$location._comment_pending"); return $location; } @@ -873,7 +899,35 @@ sub match_postcomment ($$;@) { if (! $postcomment) { return IkiWiki::FailReason->new("not posting a comment"); } - return match_glob($page, $glob); + return match_glob($page, $glob, @_); +} + +sub match_comment ($$;@) { + my $page = shift; + my $glob = shift; + + my $match=match_glob($page, "$glob/*", @_); + if ($match) { + my $type=IkiWiki::pagetype($IkiWiki::pagesources{$page}); + if ($type ne "_comment") { + return IkiWiki::FailReason->new("$page is not a comment"); + } + } + return $match; +} + +sub match_comment_pending ($$;@) { + my $page = shift; + my $glob = shift; + + my $match=match_glob($page, "$glob/*", @_); + if ($match) { + my $type=IkiWiki::pagetype($IkiWiki::pagesources{$page}); + if ($type ne "_comment_pending") { + return IkiWiki::FailReason->new("$page is not a pending comment"); + } + } + return $match; } 1 diff --git a/debian/NEWS b/debian/NEWS index 4e0c7810b..b751f1478 100644 --- a/debian/NEWS +++ b/debian/NEWS @@ -1,5 +1,11 @@ ikiwiki (3.20100505) UNRELEASED; urgency=low + There is a new "comment()" pagespec, that can be used to match a comment + on a page. It is recommended it be used instead of the old + method of using a pagespec such as "internal(comment_*)" to match + things that looked like comments. The old pagespec will now also match + comments that are held for moderation; likely not what you want. + There is a significant change to the page.tmpl template in this version. If you have locally modified versions of that template, you will need to update it to contain the following in the HTML : diff --git a/debian/changelog b/debian/changelog index 6b4ba7592..5b51a74f9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,14 @@ ikiwiki (3.20100505) UNRELEASED; urgency=low a single template, page.tmpl. * If you have a locally customised page.tmpl, it needs to be updated to set when BASEURL or FORCEBAREURL is set. + * comments: Comments pending moderation are now stored in the srcdir + alongside accepted comments, but with a `._comment_pending` extension. + * This allows easier byhand moderation, as the "_pending" need + only be stripped off and the comment be committed to version control. + * The `comment_pending()` pagespec can be used to match such unmoderated + comments, which makes it easy to add a feed of them, or a counter + indicating how many there are. + * Belatedly added a `comment()` pagespec. -- Joey Hess Wed, 05 May 2010 18:07:29 -0400 diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn index 1c99aefac..c66395f84 100644 --- a/doc/ikiwiki/pagespec.mdwn +++ b/doc/ikiwiki/pagespec.mdwn @@ -51,6 +51,8 @@ Some more elaborate limits can be added to what matches using these functions: wiki admins. * "`ip(address)`" - tests whether a modification is being made from the specified IP address. +* "`comment(glob)`" - matches comments to a page matching the glob. +* "`comment_pending(glob)`" - matches unmoderated, pending comments. * "`postcomment(glob)`" - matches only when comments are being posted to a page matching the specified glob diff --git a/doc/plugins/comments.mdwn b/doc/plugins/comments.mdwn index 775ef75a0..14bd28a04 100644 --- a/doc/plugins/comments.mdwn +++ b/doc/plugins/comments.mdwn @@ -49,5 +49,5 @@ held for moderation. (Or with the [[moderatedcomments]] plugin, all comments will be held.) Wiki admins can access the comment moderation queue via a button on their Preferences page. -The comments are stored in `.ikiwiki/comments_pending/`, and can be -deleted, or moved into the wiki's srcdir to be posted. +The unmoderated comments are stored in the `srcdir` with a filename ending +in "._comment_pending". They are not checked into revision control. diff --git a/doc/tips/comments_feed.mdwn b/doc/tips/comments_feed.mdwn index 6d4dbb803..3d6a8c449 100644 --- a/doc/tips/comments_feed.mdwn +++ b/doc/tips/comments_feed.mdwn @@ -3,8 +3,15 @@ blog can have comments added to them. Pages with comments even have special feeds that can be used to subscribe to those comments. But you'd like to add a feed that contains all the comments posted to any page. Here's how: - \[[!inline pages="internal(*/comment_*)" template=comment]] + \[[!inline pages="comment(*)" template=comment]] The special [[ikiwiki/PageSpec]] matches all comments. The [[template|templates]] causes the comments to be displayed formatted nicely. + +--- + +It's also possible to make a feed of comments that are held pending +moderation. + + \[[!inline pages="comment_pending(*)" template=comment]] diff --git a/ikiwiki.spec b/ikiwiki.spec index 76398e9fb..b2b5af3dc 100644 --- a/ikiwiki.spec +++ b/ikiwiki.spec @@ -1,5 +1,5 @@ Name: ikiwiki -Version: 3.20100504 +Version: 3.20100505 Release: 1%{?dist} Summary: A wiki compiler -- cgit v1.2.3