mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-11-03 12:54 am

[dw-free] Add a link on comments that goes to the root of the thread

[commit: http://hg.dwscoalition.org/dw-free/rev/cc90e8be4b68]

http://bugs.dwscoalition.org/show_bug.cgi?id=153

Add support for link back to root of comment thread to comments.

Patch by [personal profile] afuna.

Files modified:
  • bin/upgrading/en.dat
  • bin/upgrading/s2layers/core2.s2
  • cgi-bin/LJ/Comment.pm
  • cgi-bin/LJ/S2/EntryPage.pm
  • doc/raw/memcache-keys.txt
  • htdocs/go.bml
  • htdocs/talkread.bml
  • t/comment.t
--------------------------------------------------------------------------------
diff -r 9603e41b3cc3 -r cc90e8be4b68 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Tue Nov 03 00:50:48 2009 +0000
+++ b/bin/upgrading/en.dat	Tue Nov 03 00:54:44 2009 +0000
@@ -3599,6 +3599,8 @@ talk.spellcheck=Check spelling during pr
 
 talk.threadlink=Thread
 
+talk.threadrootlink=Thread from start
+
 talk.unscreentoreply=Unscreen to reply
 
 time.ago.day=[[num]] [[?num|day|days]] ago
diff -r 9603e41b3cc3 -r cc90e8be4b68 bin/upgrading/s2layers/core2.s2
--- a/bin/upgrading/s2layers/core2.s2	Tue Nov 03 00:50:48 2009 +0000
+++ b/bin/upgrading/s2layers/core2.s2	Tue Nov 03 00:54:44 2009 +0000
@@ -412,6 +412,7 @@ class Comment extends EntryLite
     var readonly string parent_url "URL to parent comment, or blank if a top-level comment.";
     var readonly string reply_url "URL to reply to this comment.";
     var readonly string thread_url "URL to view threaded rooted at this comment, or blank if comment has no children.";
+    var readonly string threadroot_url "URL to view the entire thread this comment is part of, or blank if a top-level comment.";
     var readonly bool screened "True if comment is in screened state.";
     var readonly bool frozen "True if comment is in frozen state.";
     var readonly bool deleted "True if comment has been deleted. Deleted comments still show up if they are the parent of a thread.";
@@ -2182,6 +2183,11 @@ property string text_comment_thread {
     example = "Thread";
     maxlength = "50";
 }
+property string text_comment_threadroot {
+    des = "Text to link to the entire thread this comment is part of";
+    example = "Thread from start";
+    maxlength = "50";
+}
 property string text_comment_expand {
     des = "Text to expand a collapsed comment thread";
     example = "Expand";
@@ -2192,6 +2198,7 @@ set text_comment_parent = "Parent";
 set text_comment_parent = "Parent";
 set text_comment_link = "Link";
 set text_comment_thread = "Thread";
+set text_comment_threadroot = "Thread from start";
 set text_comment_expand = "Expand";
 
 ##===============================
@@ -4226,6 +4233,7 @@ function Comment::print_interaction_link
         $this->print_reply_link({"linktext" => $*text_comment_reply});
         """</li>\n""";
     }
+    if ($this.threadroot_url != "") { print safe """<li class="link threadroot"><a href="$this.threadroot_url">$*text_comment_threadroot</a></li>\n""";}
     if ($this.parent_url != "") { print safe """<li class="link commentparent"><a href="$this.parent_url">$*text_comment_parent</a></li>\n"""; }
     if ($this.thread_url != "") {
         print safe """<li class="link thread"><a href="$this.thread_url">$*text_comment_thread</a></li>\n""";
diff -r 9603e41b3cc3 -r cc90e8be4b68 cgi-bin/LJ/Comment.pm
--- a/cgi-bin/LJ/Comment.pm	Tue Nov 03 00:50:48 2009 +0000
+++ b/cgi-bin/LJ/Comment.pm	Tue Nov 03 00:54:44 2009 +0000
@@ -216,15 +216,29 @@ sub absorb_row {
 }
 
 sub url {
-    my $self    = shift;
+    my ( $self, $url_args ) = @_;
 
     my $dtalkid = $self->dtalkid;
     my $entry   = $self->entry;
     my $url     = $entry->url;
 
-    return "$url?thread=$dtalkid" . LJ::Talk::comment_anchor( $dtalkid );
+    return "$url?thread=$dtalkid" . ( $url_args ? "&$url_args" : "" ) . LJ::Talk::comment_anchor( $dtalkid );
 }
 *thread_url = \&url;
+
+=head2 C<< $self->threadroot_url >>
+URL to the thread root. It would be unnecessarily expensive to look up the thread 
+root, since it is only rarely needed. So we set up a redirect then look up the 
+thread root only if the user clicks the link.
+=cut
+sub threadroot_url {
+    my ( $self, $url_args ) = @_;
+    my $dtalkid = $self->dtalkid;
+    my $jitemid = $self->entry->jitemid;
+    my $journal =$self->entry->journal->user;
+
+    return "$LJ::SITEROOT/go?redir_type=threadroot&journal=$journal&talkid=$dtalkid" . ( $url_args ? "&$url_args" : "" );
+}
 
 sub reply_url {
     my $self    = shift;
@@ -347,6 +361,56 @@ sub nodetype {
     __PACKAGE__->preload_rows([ $self->unloaded_singletons] );
     return $self->{nodetype};
 }
+
+=head2 C<< $self->threadrootid >>
+Gets the id of the topmost comment in the thread this comment is part of.
+If you just want to create a link, do not call this directly. Instead, use
+$self->threadroot_url.
+=cut
+sub threadrootid {
+
+    my ( $self ) = @_;
+
+    # if this has no parent, then this is the thread root
+    return $self->jtalkid unless $self->parenttalkid;
+
+    # if we have the information already, then just return it
+    return $self->{threadrootid} if $self->{threadrootid};
+
+    my $entry = $self->entry;
+
+    # if it is in memcache, then use the cached value
+    my $jid = $entry->journalid;
+    my $memkey = [ $jid, "talkroot:$jid:" . $self->jtalkid ];
+
+    my $cached_threadrootid = LJ::MemCache::get( $memkey );
+    if ( $cached_threadrootid ) {
+        $self->{threadrootid} = $cached_threadrootid;
+        return $cached_threadrootid;
+    }
+
+
+    # not cached anywhere; let's look it up
+
+    # get all comments to post
+    my $comments = LJ::Talk::get_talk_data( $entry->journal, 'L', $entry->jitemid ) || {};
+
+    # see if our comment exists
+    return undef unless $comments->{$self->jtalkid};
+
+    # walk up the tree
+    my $id = $self->jtalkid;
+    while ( $comments->{$id} && $comments->{$id}->{parenttalkid} ) {
+        # avoid (the unlikely chance of) an infinite loop
+        $id = delete $comments->{$id}->{parenttalkid};
+    }
+
+    # cache the value, for future lookup
+    $self->{threadrootid} = $id;
+    LJ::MemCache::set( $memkey, $id );
+    return $id;
+}
+
 
 sub parenttalkid {
     my $self = shift;
diff -r 9603e41b3cc3 -r cc90e8be4b68 cgi-bin/LJ/S2/EntryPage.pm
--- a/cgi-bin/LJ/S2/EntryPage.pm	Tue Nov 03 00:50:48 2009 +0000
+++ b/cgi-bin/LJ/S2/EntryPage.pm	Tue Nov 03 00:54:44 2009 +0000
@@ -143,6 +143,8 @@ sub EntryPage
             my $seconds_since_entry = $com->{'datepost_unix'} - $entry->logtime_unix;
             my $datetime_poster = DateTime_tz($com->{'datepost_unix'}, $pu);
 
+            my $threadroot_url;
+
             my ($edited, $edit_url, $edittime, $edittime_remote, $edittime_poster);
             if ($com->{_loaded}) {
                 my $comment = LJ::Comment->new($u, jtalkid => $com->{talkid});
@@ -154,6 +156,8 @@ sub EntryPage
                     $edittime_remote = $tz_remote ? DateTime_tz($comment->edit_time, $tz_remote) : undef;
                     $edittime_poster = DateTime_tz($comment->edit_time, $pu);
                 }
+
+                $threadroot_url = $comment->threadroot_url( LJ::viewing_style_args( %$get ) ) if $com->{parenttalkid};
             }
 
             my $subject_icon = undef;
@@ -235,6 +239,7 @@ sub EntryPage
                 'full' => $com->{'_loaded'} ? 1 : 0,
                 'depth' => $depth,
                 'parent_url' => $par_url,
+                threadroot_url => $threadroot_url,
                 'screened' => $com->{'state'} eq "S" ? 1 : 0,
                 'frozen' => $com->{'state'} eq "F" ? 1 : 0,
                 'deleted' => $com->{'state'} eq "D" ? 1 : 0,
diff -r 9603e41b3cc3 -r cc90e8be4b68 doc/raw/memcache-keys.txt
--- a/doc/raw/memcache-keys.txt	Tue Nov 03 00:50:48 2009 +0000
+++ b/doc/raw/memcache-keys.txt	Tue Nov 03 00:54:44 2009 +0000
@@ -13,6 +13,7 @@
 <uid> talk2row:<uid>:<jtalkid> == packed data
 <uid> talk2ct:<uid> == # rows for user
 <uid> talkleftct:<uid> == # rows for user
+<uid> talkroot:<uid>:<jtalkid> == scalar: root of the thread containing this comment
 
 <uid> logtext:<cid>:<uid>:<jitemid> == [ subject, text ]
 <uid> logprop:<uid>:<jitemid> == { propname => $value, ... }
diff -r 9603e41b3cc3 -r cc90e8be4b68 htdocs/go.bml
--- a/htdocs/go.bml	Tue Nov 03 00:50:48 2009 +0000
+++ b/htdocs/go.bml	Tue Nov 03 00:54:44 2009 +0000
@@ -6,7 +6,7 @@
  $title = $ML{'.defaulttitle'};
  $body = $ML{'.defaultbody'};
 
- # S2 Redirector
+ # S2 monthview Redirector
  if ($POST{'redir_type'} eq "monthview") {
      my $user = LJ::canonical_username($POST{'redir_user'});
      my $vhost;
@@ -20,6 +20,20 @@
      return BML::redirect("$base/$year/$month/");
  }
 
+ # comment thread root redirector
+ my $talkid = $GET{talkid}+0;
+ if ( $GET{redir_type} eq "threadroot" && $talkid ) {
+    my $journal = $GET{journal};
+    my $u = LJ::load_user( $journal );
+    return unless $u;
+
+    my $comment = LJ::Comment->new( $u, dtalkid => $talkid );
+    return unless $comment;
+
+    my $threadroot = LJ::Comment->new( $u, jtalkid => $comment->threadrootid );
+    return BML::redirect(  $threadroot->url( LJ::viewing_style_args( %GET ) ) );
+ }
+  
  # prev/next talkread links
  my $itemid = $GET{'itemid'}+0;
  if ($GET{'journal'} && $itemid) 
diff -r 9603e41b3cc3 -r cc90e8be4b68 htdocs/talkread.bml
--- a/htdocs/talkread.bml	Tue Nov 03 00:50:48 2009 +0000
+++ b/htdocs/talkread.bml	Tue Nov 03 00:54:44 2009 +0000
@@ -48,6 +48,7 @@ body<=
                readcomments    talk.commentsread
                parent          talk.parentlink
                thread          talk.threadlink
+               threadroot      talk.threadrootlink
                expand          talk.expandlink
                replythis       talk.replytothis
                unscreentoreply talk.unscreentoreply
@@ -711,6 +712,9 @@ body<=
 
                 my $parentid = $post->{'parenttalkid'} || $post->{'parenttalkid_actual'};
                 if ($parentid != 0) {
+                    my $rooturl = $comment->threadroot_url( LJ::viewing_style_args( %GET ) );
+                    $ret .= "(<a href='$rooturl'>$T{'threadroot'}</a>)";
+
                     my $dpid = $parentid * 256 + $init->{'anum'};
                     $ret .= "(<a href='" . LJ::Talk::talkargs($talkurl, "thread=$dpid", $stylemine, $formatlight);
                     $ret .= LJ::Talk::comment_anchor( $dpid ) . "'>$T{'parent'}</a>)";
diff -r 9603e41b3cc3 -r cc90e8be4b68 t/comment.t
--- a/t/comment.t	Tue Nov 03 00:50:48 2009 +0000
+++ b/t/comment.t	Tue Nov 03 00:54:44 2009 +0000
@@ -1,7 +1,7 @@
 # -*-perl-*-
 
 use strict;
-use Test::More tests => 189;
+use Test::More tests => 405;
 use lib "$ENV{LJHOME}/cgi-bin";
 require 'ljlib.pl';
 require 'ljprotocol.pl';
@@ -266,6 +266,38 @@ sub run_tests {
             ok( $access_ct{data} == 1, "$step: Only one talk data access with legacy interaction");
             ok( $access_ct{text} == 1, "$step: Only one text data access with legacy interaction");
             ok( $access_ct{props} == 1, "$step: Only one prop data access with legacy interaction");
+
+            # Add to the tree:
+            # - child 6
+            #   + child 6.1
+            #     + child 6.1.1
+            #       + child 6.1.1.1
+            my $comment = $entry->t_enter_comment;
+            my $curr = [ $comment => [] ];
+            push @tree, $curr;
+            foreach ( 1..3 ) {
+                $comment = $comment->t_reply;
+                push @{$curr->[1]}, $comment;
+            }
+
+            # look up root
+            foreach my $parent (map { $_->[0] } @tree) {
+                ok ( $parent->threadrootid eq $parent->jtalkid, "Comment depth 1: this is the thread root" );
+
+                my @children = $parent->children;
+                foreach my $child ( @children ) {
+                    ok ( $child->parenttalkid == $child->threadrootid, "Comment depth 2: thread root and parent are equivalent." );
+
+                    my $descendant = $child;
+                    my $depth = 2;
+                    foreach ( $descendant->children ) {
+                        ok ( $child->parenttalkid == $descendant->threadrootid, "Comment depth $depth: thread root is no longer directly linked to this comment." );
+
+                        $depth++;
+                        $descendant = $_;
+                    }
+                }
+            }
         } 
     }
 
--------------------------------------------------------------------------------
azurelunatic: Vivid pink Alaskan wild rose. (Default)

[personal profile] azurelunatic 2009-11-03 07:01 am (UTC)(link)
Mwah!
yvi: Kaylee half-smiling, looking very pretty (Default)

[personal profile] yvi 2009-11-03 08:08 am (UTC)(link)
Yay!
turlough: purple crocuses ((mcr) bob approves)

[personal profile] turlough 2009-11-03 02:08 pm (UTC)(link)
Yay!