in reply to Graphical Hierarchical Tree
That being said, this code is linear to the number of posts, and does not suffer from problems from extra deeply nested structures.
It also handles moderation and some other things. Please understand, it has some serious issues, and it is being re-vamped.
sub getThreads { # main code section for comment display # here's where all the deep magic happens. # The algorithm is simple, but has a speed issue. # 1. select all comments from the db # 2. store the comment contents in %text, keyed by ID # 3. Put the id of the parent posting of a given posting in %p +arent, keyed by ID # By nature of the way comments are entered, # we know that a given reply to a comment will always # have a larger ID than its parent, # 4. read %parent in reverse order # take the current posting and append it to the parent # since we're in reverse order, parent will always exist +. and the # text will appear after the parent, with the newest rep +lies first on the page # if parent is this post, leave alone -> is a top level +post # reply comments are thus added to the top level post # 5. read %text in reverse order as well # append the text to the output data # this will give a reverse order thread, but with the ra +ther # cool side effect of putting the latest thread at the t +op. # so the latest discussion comes first on the page. # so less scrolling for most posters. # my ($table,$id,$mode,$dirc,$type,$path,$modmode) = @_; if($id !~ /^\d{1,10}$/) { return &readfile("$doc_root/templates/badvar.html"); } my ($output,$comment,$thread, $indent, $full, $sort, $cursor); if($mode eq 'flat') { $indent = 0; $full = 1; } elsif($mode eq 'thread') { $indent = 1; $full = 0; } elsif($mode eq 'nested') { $indent = 1; $full = 1; } elsif($mode eq 'in-order') { $indent = 0; $full = 0; $sort = "ID $dirc"; } elsif($mode eq 'indexed' || $mode eq '') { $indent = 1; $full = 1; } # select all from the table my ($c) = &sqlSelectMany("$table.ID,$table.USERNAME,$table.SUB +JECT,$table.MESSAGE,$table.TIMESTAMP,$table.STATUS,$table.PARENT,$tab +le.SUB_PARENT,$table.LEVEL,USERS.EMAIL as EMAIL", "$table,USERS", "ITEM='$id' && STATUS != 'dead' && USERS.USERNAME=$tab +le.USERNAME", "order by ID"); my %parent; my %text; if($c->rows >= 1) { while($cursor=$c->fetchrow_hashref) { my $tid = $cursor->{'ID'}; my $username = $cursor->{'USERNAME'}; my $subject = $cursor->{'SUBJECT'}; my $message = $cursor->{'MESSAGE'}; $message =~ s/\n/<br>/g; my $timestamp = &post_date($cursor->{'TIMEST +AMP'}); my $status = $cursor->{'STATUS'}; my $parent = $cursor->{'PARENT'}; my $sub_parent = $cursor->{'SUB_PARENT'}; my $level = $cursor->{'LEVEL'}; my $email = $cursor->{'EMAIL'}; $parent{$tid}=$sub_parent; if($status eq "active" || ($modmode eq 'yes' & +& $status ne 'kthread')) { if($modmode eq 'yes' && $status ne 'ac +tive') { $subject .= " <MODERATED& +gt;"; } if(length($email) <= 4) { $email=""; } # parent is hash containing the parent + of this posting } elsif ($status eq 'dthread') { $subject = "<Deleted>"; $message = "This message has been mode +rated down, score -1 :)"; $username = "<Deleted>"; $email = ""; } elsif($status eq 'inactive' || $status eq 'kth +read') { my ($leafchk) = &sqlSelectMany("PARENT +,ID", $table, "PARENT = $tid"); my $leafrows = $leafchk->rows; my $lfr = $leafchk->fetchrow_hashref; $leafchk->finish; if($leafrows > 1 || ($leafrows == 1 && $lfr->{'PARENT'} == $lfr->{'I +D'})) { $subject = "<Deleted>"; $message = "This message has b +een moderated down, score -1"; $username = "<Deleted>"; $email = ""; } else { next; } } else { $subject = "<Error>"; $message = "This is an Error and is be +ing looked into."; $username = "lt;Error>"; $email = ""; } $text{$tid}=&posting($indent,$full,$level,$mod +e, $id,$tid,$level,$subject,$message,'Yes +', $email,$username,$timestamp,$type,$pat +h); # $message is the comment text of this posting } foreach $node (sort reverse_number (keys (%text)) ) { # for every posting numbered $node # start at the last posting # and go backwards if ( $node == $parent{$node}) { # this is parented by itself. # leave it alone, because its a top le +vel posting } else { $text{$parent{$node}}.=$text{$node}; $text{$node}=""; # attach this text to its parent's tex +t # delete it from the text hash # so that we can just run thru the has +h to display # the entire posting contents } } foreach $node ( sort reverse_number (keys %text )) { $output.=$text{$node}; # finally , add all the output reverse sequent +ially } } else { $output = qq| <tr bgcolor="#FFFFFF"> <td align=\"cente +r\"> <font face="Verdana, Arial, Helvetica, sans-se +rif"> <br><br> <b>No threads are currently available +.</b><br><br>|; } $c->finish; $output .= qq|</font></td></tr>|; return($output); }
|
|---|