]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/comments.pm
sidebar plugin optimisations
[git.ikiwiki.info.git] / IkiWiki / Plugin / comments.pm
index 2ad422f5f678028c83bfe3a9fbc68e7528135414..0aa043215b35a5ab32b2219dfc5410ac64c507cc 100644 (file)
@@ -21,6 +21,8 @@ my %commentstate;
 sub import {
        hook(type => "checkconfig", id => 'comments',  call => \&checkconfig);
        hook(type => "getsetup", id => 'comments',  call => \&getsetup);
+       hook(type => "preprocess", id => 'comment', call => \&preprocess);
+       # here for backwards compatability with old comments
        hook(type => "preprocess", id => '_comment', call => \&preprocess);
        hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi);
        hook(type => "htmlize", id => "_comment", call => \&htmlize);
@@ -36,6 +38,7 @@ sub getsetup () {
                plugin => {
                        safe => 1,
                        rebuild => 1,
+                       section => "web",
                },
                comments_pagespec => {
                        type => 'pagespec',
@@ -169,9 +172,8 @@ sub preprocess {
                else {
                        $commentauthorurl = IkiWiki::cgiurl(
                                do => 'goto',
-                               page => (length $config{userdir}
-                                       ? "$config{userdir}/$commentuser"
-                                       : "$commentuser"));
+                               page => IkiWiki::userpage($commentuser)
+                       );
 
                        $commentauthor = $commentuser;
                }
@@ -219,10 +221,12 @@ sub preprocess {
        }
 
        if (defined $params{subject}) {
-               $pagestate{$page}{meta}{title} = $params{subject};
+               # decode title the same way meta does
+               eval q{use HTML::Entities};
+               $pagestate{$page}{meta}{title} = decode_entities($params{subject});
        }
 
-       if ($params{page} =~ m/\/(\Q$config{comments_pagename}\E\d+)$/) {
+       if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) {
                $pagestate{$page}{meta}{permalink} = urlto(IkiWiki::dirname($params{page}), undef, 1).
                        "#".page_to_id($params{page});
        }
@@ -287,10 +291,15 @@ sub editcomment ($$) {
        else {
                $type = $config{default_pageext};
        }
+
+
        my @page_types;
        if (exists $IkiWiki::hooks{htmlize}) {
-               @page_types = grep { ! /^_/ } keys %{$IkiWiki::hooks{htmlize}};
+               foreach my $key (grep { !/^_/ } keys %{$IkiWiki::hooks{htmlize}}) {
+                       push @page_types, [$key, $IkiWiki::hooks{htmlize}{$key}{longname} || $key];
+               }
        }
+       @page_types=sort @page_types;
 
        $form->field(name => 'do', type => 'hidden');
        $form->field(name => 'sid', type => 'hidden', value => $session->id,
@@ -317,6 +326,13 @@ sub editcomment ($$) {
                        force => 1);
        }
 
+       if (! defined $session->param('name')) {
+               # Make signinurl work and return here.
+               $form->tmpl_param(signinurl => IkiWiki::cgiurl(do => 'signin'));
+               $session->param(postsignin => $ENV{QUERY_STRING});
+               IkiWiki::cgi_savesession($session);
+       }
+
        # The untaint is OK (as in editpage) because we're about to pass
        # it to file_pruned anyway
        my $page = $form->field('page');
@@ -363,9 +379,7 @@ sub editcomment ($$) {
        IkiWiki::check_canedit($page, $cgi, $session);
        $postcomment=0;
 
-       my $location=unique_comment_location($page, $config{srcdir});
-
-       my $content = "[[!_comment format=$type\n";
+       my $content = "[[!comment format=$type\n";
 
        # FIXME: handling of double quotes probably wrong?
        if (defined $session->param('name')) {
@@ -396,8 +410,11 @@ sub editcomment ($$) {
        my $subject = $form->field('subject');
        if (defined $subject && length $subject) {
                $subject =~ s/"/"/g;
-               $content .= " subject=\"$subject\"\n";
        }
+       else {
+               $subject = "comment ".(num_comments($page, $config{srcdir}) + 1);
+       }
+       $content .= " subject=\"$subject\"\n";
 
        $content .= " date=\"" . decode_utf8(strftime('%Y-%m-%dT%H:%M:%SZ', gmtime)) . "\"\n";
 
@@ -407,6 +424,8 @@ sub editcomment ($$) {
        $editcontent =~ s/"/\\"/g;
        $content .= " content=\"\"\"\n$editcontent\n\"\"\"]]\n";
 
+       my $location=unique_comment_location($page, $content, $config{srcdir});
+
        # This is essentially a simplified version of editpage:
        # - the user does not control the page that's created, only the parent
        # - it's always a create operation, never an edit
@@ -444,7 +463,7 @@ sub editcomment ($$) {
 
                if (! $ok) {
                        my $penddir=$config{wikistatedir}."/comments_pending";
-                       $location=unique_comment_location($page, $penddir);
+                       $location=unique_comment_location($page, $content, $penddir);
                        writefile("$location._comment", $penddir, $content);
                        IkiWiki::printheader($session);
                        print IkiWiki::misctemplate(gettext(gettext("comment stored for moderation")),
@@ -540,7 +559,7 @@ sub commentmoderation ($$) {
                                if ($action eq 'Accept') {
                                        my $content=eval { readfile($file) };
                                        next if $@; # file vanished since form was displayed
-                                       my $dest=unique_comment_location($page, $config{srcdir})."._comment";
+                                       my $dest=unique_comment_location($page, $content, $config{srcdir})."._comment";
                                        writefile($dest, $config{srcdir}, $content);
                                        if ($config{rcs} and $config{comments_commit}) {
                                                IkiWiki::rcs_add($dest);
@@ -719,39 +738,43 @@ sub pagetemplate (@) {
                }
 
                if ($shown && commentsopen($page)) {
-                       my $addcommenturl = IkiWiki::cgiurl(do => 'comment',
-                               page => $page);
-                       $template->param(addcommenturl => $addcommenturl);
+                       $template->param(addcommenturl => addcommenturl($page));
                }
        }
 
-       if ($template->query(name => 'commentsurl')) {
-               if ($shown) {
+       if ($shown) {
+               if ($template->query(name => 'commentsurl')) {
                        $template->param(commentsurl =>
                                urlto($page, undef, 1).'#comments');
                }
-       }
 
-       if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
-               if ($shown) {
+               if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
                        # This will 404 until there are some comments, but I
                        # think that's probably OK...
                        $template->param(atomcommentsurl =>
                                urlto($page, undef, 1).'comments.atom');
                }
-       }
 
-       if ($template->query(name => 'commentslink')) {
-               # XXX Would be nice to say how many comments there are in
-               # the link. But, to update the number, blog pages
-               # would have to update whenever comments of any inlines
-               # page are added, which is not currently done.
-               if ($shown) {
-                       $template->param(commentslink =>
-                               htmllink($page, $params{destpage}, $page,
-                                       linktext => gettext("Comments"),
+               if ($template->query(name => 'commentslink')) {
+                       my $num=num_comments($page, $config{srcdir});
+                       my $link;
+                       if ($num > 0) {
+                               $link = htmllink($page, $params{destpage}, $page,
+                                       linktext => sprintf(ngettext("%i comment", "%i comments", $num), $num),
                                        anchor => "comments",
-                                       noimageinline => 1));
+                                       noimageinline => 1
+                               );
+                       }
+                       elsif (commentsopen($page)) {
+                               $link = "<a href=\"".addcommenturl($page)."\">".
+                                       #translators: Here "Comment" is a verb;
+                                       #translators: the user clicks on it to
+                                       #translators: post a comment.
+                                       gettext("Comment").
+                                       "</a>";
+                       }
+                       $template->param(commentslink => $link)
+                               if defined $link;
                }
        }
 
@@ -799,15 +822,34 @@ sub pagetemplate (@) {
        }
 }
 
-sub unique_comment_location ($) {
+sub addcommenturl ($) {
+       my $page=shift;
+
+       return IkiWiki::cgiurl(do => 'comment', page => $page);
+}
+
+sub num_comments ($$) {
        my $page=shift;
        my $dir=shift;
 
+       my @comments=glob("$dir/$page/$config{comments_pagename}*._comment");
+       return @comments;
+}
+
+sub unique_comment_location ($$$) {
+       my $page=shift;
+
+       eval q{use Digest::MD5 'md5_hex'};
+       error($@) if $@;
+       my $content_md5=md5_hex(Encode::encode_utf8(shift));
+
+       my $dir=shift;
+
        my $location;
-       my $i = 0;
+       my $i = num_comments($page, $dir);
        do {
                $i++;
-               $location = "$page/$config{comments_pagename}$i";
+               $location = "$page/$config{comments_pagename}${i}_${content_md5}";
        } while (-e "$dir/$location._comment");
 
        return $location;
@@ -815,17 +857,14 @@ sub unique_comment_location ($) {
 
 sub page_to_id ($) {
        # Converts a comment page name into a unique, legal html id
-       # addtibute value, that can be used as an anchor to link to the
+       # attribute value, that can be used as an anchor to link to the
        # comment.
        my $page=shift;
 
-       # It needs to start with a letter.
-       $page="comment_".$page;
-
-       # Encode any illegal characters.
-       $page=~s/([^A-Za-z0-9-_:.])/"__".ord($1)."__"/eg;
+       eval q{use Digest::MD5 'md5_hex'};
+       error($@) if $@;
 
-       return $page;
+       return "comment-".md5_hex(Encode::encode_utf8(($page)));
 }
        
 package IkiWiki::PageSpec;