# ==================================================================
# Gossamer Forum - Advanced web community
#
# Website : http://gossamer-threads.com/
# Support : http://gossamer-threads.com/scripts/support/
# Revision : $Id: Post.pm,v 1.103 2002/07/16 18:29:06 jagerman Exp $
#
# Copyright (c) 2001 Gossamer Threads Inc. All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================
#
# Every post function other than viewing or writing (for example,
# deleting) goes in here.
#
package GForum::Post;
use strict;
use vars qw/@EXPORT_OK/;
use GForum qw/:user :forum $DB $IN $CFG $USER $GUEST $SESSION/;
use GForum::Convert; # exports escape_html(), unescape_html(), escape_string(), unescape_string(), convert_signature(), and convert_markup()
use Exporter;
use constants
THREADED => 0,
FLAT => 1;
use GT::AutoLoader;
@EXPORT_OK = qw/THREADED FLAT/;
$COMPILE{icons} = __LINE__ . <<'END_OF_SUB';
sub icons { +{ icons => [(shift() ? {} : ()), map +{ icon_name => $_, icon_filename => $CFG->{post_icons}->{$_} }, keys %{$CFG->{post_icons}}] } }
END_OF_SUB
# Called from the admin templates
$COMPILE{icon_add} = __LINE__ . <<'END_OF_SUB';
sub icon_add {
my ($icon_name, $icon_filename) = @_;
if (exists $CFG->{post_icons}->{$icon_name}) {
return { add_success => 0, reason => "An icon with that name already exists" }
}
$CFG->{post_icons}->{$icon_name} = $icon_filename;
$CFG->save();
return { add_success => 1 }
}
END_OF_SUB
# Called from the admin templates
$COMPILE{icon_delete} = __LINE__ . <<'END_OF_SUB';
sub icon_delete {
my $icon_name = shift;
if (not exists $CFG->{post_icons}->{$icon_name}) {
return { delete_sucess => 0, reason => "No such icon" }
}
delete $CFG->{post_icons}->{$icon_name};
$CFG->save();
return { delete_success => 1 }
}
END_OF_SUB
$COMPILE{move} = __LINE__ . <<'END_OF_SUB';
sub move {
shift;
my ($do, $func) = @_;
my ($Forum, $Post) = ($DB->table('Forum'), $DB->table('Post'));
my $page = $func->{page};
my $root_id = $IN->param('root_id');
my $old_post = $Post->select({ post_id => $root_id })->fetchrow_hashref;
die "Unable to move pointer" if $old_post->{post_moved};
my $forum_id = $IN->param('forum_id');
my @post_ids = ($root_id, $Post->select(post_id => { post_root_id => $root_id })->fetchall_list);
$Post->update({ forum_id_fk => $forum_id }, { post_id => \@post_ids });
my $post = $DB->table('Post', 'User')->select(left_join => { post_id => $root_id })->fetchrow_hashref;
normalize($post);
my $old_forum = $DB->table('Forum', 'Category')->select({ forum_id => $old_post->{forum_id_fk} })->fetchrow_hashref;
if ($old_forum->{forum_move_pointer} and not $IN->param('skip_pointer')) {
$Post->insert({
post_ip => $ENV{REMOTE_ADDR} || '0.0.0.0',
post_time => 2_000_000_000 - $old_post->{post_latest_reply},
post_icon => $old_post->{post_icon},
post_moved => 1,
user_id_fk => $old_post->{user_id_fk},
forum_id_fk => $old_post->{forum_id_fk},
post_subject => $old_post->{post_subject},
post_message => '',
post_username => $old_post->{post_username},
post_moved_id => $old_post->{post_id},
post_father_id => 0
});
$DB->table('User')->update({ user_posts => \'user_posts - 1' }, { user_id => $old_post->{user_id_fk} }) if $old_post->{user_id_fk};
}
my $forum = $DB->table('Forum', 'Category')->select({ forum_id => $forum_id })->fetchrow_hashref;
require GForum::Forum;
GForum::Forum::normalize($old_forum);
GForum::Forum::normalize($forum);
@$forum{map "old_$_", keys %$old_forum} = values %$old_forum;
return(
$page->{moved} => {
%$post,
%$forum
}
);
}
END_OF_SUB
# Detaching is just like moving, except that it works on a reply.
$COMPILE{detach} = __LINE__ . <<'END_OF_SUB';
sub detach {
shift;
my ($do, $func) = @_;
my ($Forum, $Post, $PostView) = ($DB->table('Forum'), $DB->table('Post'), $DB->table('PostView'));
my $tree = $Post->tree;
my $page = $func->{page};
my $post_id = $IN->param('post_id');
my ($old_forum_id, $old_root_id, $old_depth) = $Post->select('forum_id_fk', 'post_root_id', 'post_depth' => { post_id => $post_id })->fetchrow;
if (!$old_root_id) { # This is really a move (only happens if you refresh the move confirmation page)
$IN->param(root_id => $post_id);
return GForum::do_func('post_move');
}
my $new_forum_id = $IN->param('forum_id');
my @ancestors = @{$tree->parent_ids(id => $post_id)};
my @new_thread_ids = ($post_id, @{$tree->child_ids(id => $post_id)});
my @old_thread_ids = ($old_root_id, $Post->select(post_id => { post_root_id => $old_root_id })->fetchall_list) if $old_root_id;
# @old_thread_ids contains everything in the root - we now have to take the new_thread_ids out of it.
OLD: for (my $o = 0; $o < @old_thread_ids; $o++) {
for (my $n = 0; $n < @new_thread_ids; $n++) {
if ($old_thread_ids[$o] == $new_thread_ids[$n]) {
splice @old_thread_ids, $o, 1;
$o < @old_thread_ids ? redo OLD : last OLD; # redo doesn't check the for loop condition
}
}
}
my $old_thread_views = $PostView->select(post_thread_views => { post_id_fk => $old_root_id })->fetchrow;
$PostView->update({ post_thread_views => $old_thread_views }, { post_id_fk => $post_id }); # The new root inherits the thread views of the old root
$Post->update({ post_father_id => 0 }, { post_id => $post_id });
my @update_forums = $new_forum_id;
if ($old_forum_id != $new_forum_id) { # A detachment doesn't necessarily go to a new forum
$Post->update({ forum_id_fk => $new_forum_id }, { post_id => \@new_thread_ids });
push @update_forums, $old_forum_id;
}
# Now all the ancestors of the new root post have to have their number of replies reduced:
my $fewer_replies = @new_thread_ids;
$Post->update({ post_replies => \"post_replies - $fewer_replies" }, { post_id => \@ancestors });
# And the old thread has to have all of its latest_reply and latest_poster times updated.
$Post->rebuild_latest(@old_thread_ids);
my $post = $DB->table('Post', 'User')->select(left_join => { post_id => $post_id })->fetchrow_hashref;
normalize($post);
my $forum = $DB->table('Forum', 'Category')->select({ forum_id => $new_forum_id })->fetchrow_hashref;
require GForum::Forum;
GForum::Forum::normalize($forum);
my $old_forum;
if ($old_forum_id == $new_forum_id) {
$old_forum = $forum;
}
else {
$old_forum = $DB->table('Forum', 'Category')->select({ forum_id => $old_forum_id })->fetchrow_hashref;
GForum::Forum::normalize($old_forum) if $old_forum_id != $new_forum_id;
}
@$forum{map "old_$_", keys %$old_forum} = values %$old_forum;
return(
$page->{detached} => {
%$post,
%$forum
}
);
}
END_OF_SUB
$COMPILE{lock} = __LINE__ . <<'END_OF_SUB';
sub lock {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('root_id');
$DB->table('Post')->update({ post_locked => 1 }, { post_id => $post_id });
GForum::do_func($IN->param('redo'));
}
END_OF_SUB
$COMPILE{unlock} = __LINE__ . <<'END_OF_SUB';
sub unlock {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('root_id');
$DB->table('Post')->update({ post_locked => undef }, { post_id => $post_id });
GForum::do_func($IN->param('redo'));
}
END_OF_SUB
$COMPILE{keep} = __LINE__ . <<'END_OF_SUB';
sub keep {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('root_id');
$DB->table('Post')->update({ post_keep => 1 }, { post_id => $post_id });
GForum::do_func($IN->param('redo'));
}
END_OF_SUB
$COMPILE{unkeep} = __LINE__ . <<'END_OF_SUB';
sub unkeep {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('root_id');
$DB->table('Post')->update({ post_keep => 0 }, { post_id => $post_id });
GForum::do_func($IN->param('redo'));
}
END_OF_SUB
# This marks all posts in all forums as read. GForum::Forum::mark_all_new marks
# all posts in a forum as read.
$COMPILE{mark_all_read} = __LINE__ . <<'END_OF_SUB';
sub mark_all_read {
if ($USER) {
my $UserNew = $DB->table('UserNew');
my $now = time;
my @forums = $DB->table('Forum')->select('forum_id')->fetchall_list;
# Don't worry about permissions, even if we set a hidden forum as read it's no big deal.
for my $forum_id (@forums) {
if ($UserNew->count({ forum_id_fk => $forum_id, user_id_fk => $USER->{user_id} })) {
$UserNew->update({ usernew_last => $now }, { forum_id_fk => $forum_id, user_id_fk => $USER->{user_id} });
}
else {
$UserNew->insert({ forum_id_fk => $forum_id, user_id_fk => $USER->{user_id}, usernew_last => $now });
}
if ($SESSION) {
$SESSION->{info}->{session_data}->{usernew}->{$forum_id} = $now;
$SESSION->{info}->{session_data}->{userlast}->{$forum_id} = $now;
$SESSION->save();
}
}
# Delete any "new" posts from the PostNew table.
$DB->table('PostNew')->delete({ user_id_fk => $USER->{user_id} });
}
GForum::do_func($IN->param('redo'));
}
END_OF_SUB
# Takes one argument, a post hashref, or array ref of post hashrefs. The posts
# should have at LEAST:
# - post_id
# - post_time
# - forum_id_fk
# - user_id_fk
# - post_replies # (optional; these two are required if
# - post_latest_reply # you want 'new_replies' to be set)
# Each post will have post_new set to either 1 or undef, and, if you specify
# post_replies and post_latest_reply, will also have new_replies set to 1 or
# undef.
sub _calc_new {
my $posts = ref $_[0] eq 'ARRAY' ? shift : [shift];
return unless $SESSION; # If you don't have a session, you can't have new posts
my $data = $SESSION->data();
my (%anc_info, $anc_loaded); # Used for a bit of caching
for my $post (@$posts) {
if (not $data->{posts}->{$post->{forum_id_fk}}->{$post->{post_id}} # Not previously viewed
and $post->{post_time} > ($data->{userlast}->{$post->{forum_id_fk}} || 0) # Posted since the last time we were in this forum BEFORE the current session
and $post->{user_id_fk} != $USER->{user_id}) { # Not posted by the current user
$post->{post_new} = 1;
}
else {
$post->{post_new} = undef;
}
if ($post->{post_replies} and # There are replies
2_000_000_000 - $post->{post_latest_reply} > ($data->{userlast}->{$post->{forum_id_fk}} || 0)) { # Posted since the last time we were in this forum BEFORE the current session
# There _might_ be new ones, but we need to do a check to be sure.
my %reply; # child_post_id => child_post_time
my %replier; # child_post_id => child_user_id
unless ($anc_loaded++) { # Do a little caching here to save on the number of selects
my $tree = $DB->table('Post')->tree;
my $children = $tree->children(id => [map $_->{post_id}, @$posts], cols => ['post_id', 'post_time', 'user_id_fk']);
for my $anc (keys %$children) {
for my $post (@{$children->{$anc}}) {
push @{$anc_info{$anc}}, [@$post{'post_id', 'post_time', 'user_id_fk'}];
}
}
}
for (@{$anc_info{$post->{post_id}}}) {
$reply{$_->[0]} = $_->[1];
$replier{$_->[0]} = $_->[2];
}
my $new_replies;
for (keys %reply) {
if (!$data->{posts}->{$post->{forum_id_fk}}->{$_} and # Not previously viewed
$reply{$_} > $data->{userlast}->{$post->{forum_id_fk}} and # Posted since the last time we were in this forum BEFORE the current session
$replier{$_} != $USER->{user_id}) { # Not posted by the current user
$new_replies = 1;
last;
}
}
$post->{new_replies} = $new_replies;
}
elsif (defined $post->{post_replies}) {
$post->{new_replies} = undef;
}
}
$posts;
}
# Takes one argument and does whatever needs to be done prior to display of the post(s).
# To normalize a single post, you pass in a hash ref from $DB->table('Post', 'User')
# To normalize multiple posts, you pass in a single array reference containing the hash
# refs from $DB->table('Post', 'User');
# This subroutine returns the post (or posts), but you don't have to use it - the post
# hashref(s) are directly altered as required.
sub normalize {
my $p = shift;
GT::Plugins->dispatch($CFG->{admin_root_path} . '/Plugins/GForum', "post_normalize", sub { return _plg_normalize(@_) }, $p);
}
sub _plg_normalize {
my $posts = ref $_[0] eq 'ARRAY' ? shift : ref $_[0] eq 'HASH' ? [shift] : return;
return unless @$posts;
require GT::Date;
{
# Normalize any users first:
my @posts_with_users = grep $_->{user_id}, @$posts;
if (@posts_with_users) {
require GForum::User;
GForum::User::normalize(\@posts_with_users);
}
}
my $pv = $DB->table('PostView');
my @post_ids = map $_->{post_id}, @$posts;
my %views = map { ($_->[0] => [ $_->[1], $_->[2] ]) } @{$DB->table('PostView')->select('post_id_fk', 'post_views', 'post_thread_views' => { post_id_fk => \@post_ids })->fetchall_arrayref} if @post_ids;
for my $pid (@post_ids) {
unless ($views{$pid}) { # Just in case the PostView insert failed - it shouldn't, but it's happened before.
$DB->table('PostView')->insert({ post_id_fk => $pid, post_views => 0, post_thread_views => 0 });
$views{$pid} = [0, 0];
}
}
my @forum_ids;
{
my %forum_ids;
for (@$posts) {
push @forum_ids, $_->{forum_id_fk} unless $forum_ids{$_->{forum_id_fk}}++;
}
}
my %moderators; # { forum_id => { user_id => 1, user_id => 1, ... }, ... }
if (@forum_ids) {
my $sth = $DB->table('ForumModerator')->select('forum_id_fk', 'user_id_fk', { forum_id_fk => \@forum_ids });
while (my ($fid, $uid) = $sth->fetchrow) {
$moderators{$fid}->{$uid} = 1;
}
}
if ($SESSION) {
_calc_new($posts);
}
my $literal = $IN->param('literal');
for my $post (@$posts) {
@$post{'post_views', 'post_thread_views'} = @{$views{$post->{post_id}}} if exists $views{$post->{post_id}};
$post->{post_user_is_moderator} = ($post->{forum_id_fk} and $post->{user_id_fk} and $moderators{$post->{forum_id_fk}}->{$post->{user_id_fk}});
$post->{post_latest_reply} = 2_000_000_000 - $post->{post_latest_reply};
$post->{post_date} = GForum::date($post->{post_time});
$post->{post_latest_reply_date} = GForum::date($post->{post_latest_reply});
if ($post->{post_deleted}) {
$post->{post_deleted_date} = GForum::date($post->{post_deleted_time});
}
if ($post->{post_last_edit_username}) {
$post->{post_last_edit_date} = GForum::date($post->{post_last_edit_time});
}
if (!$post->{user_id}) { # Handle any posts without users now
$post->{user_username} = $post->{post_username};
$post->{user_title} = \GForum::language('USER_DELETED');
$post->{user_signature} = $post->{post_signature_deleted};
}
my $converted = 0;
my $message = $post->{post_message};
# These variables have to be copied out here because of replies - the keys of $post
# are renamed "parent_post_*", which breaks this closure if using $post->{...} :(
my $style = $post->{post_style};
my $signature = $post->{$post->{user_id} ? "user_signature" : "post_signature_deleted"};
$post->{post_message} = sub {
return \$message if $converted++;
if ($style < 2 or $literal) { # 2 and 3 allow HTML, 0 and 1 don't.
escape_html($message);
}
if ($style % 2 and not $literal) { # 1 and 3 allow Markup
convert_markup(\$message);
}
unless ($CFG->{signature_allow_html} and not $literal) {
escape_html($signature);
}
if ($CFG->{signature_allow_markup} == 2 and not $literal) {
convert_markup(\$signature);
}
elsif ($CFG->{signature_allow_markup} == 1 and not $literal) {
my $save = $GForum::Convert::No_Image; # Implement local() without local()
$GForum::Convert::No_Image = 1;
convert_markup(\$signature);
$GForum::Convert::No_Image = $save;
}
if (!$CFG->{signature_allow_html} and !$CFG->{signature_allow_markup} or $literal) {
$signature =~ s/ / /g;
}
convert_signature(\$message, \$signature);
$message =~ s/\r?\n/
/g; # That space keeps IE from condensing multiple
's into 1. It is only needed where you have
, but that regex would slow the converter down quite a bit.
$message =~ s/^( +)/' ' x length $1/gem;
\$message;
};
$post->{post_depth} ||= 0;
if ($USER) {
if ($USER->{user_default_post_display} == THREADED) {
$post->{post_display_is_threaded} = 1;
}
else {
$post->{post_display_is_flat} = 1;
}
}
elsif ($CFG->{post_display_default} eq 'post_view_flat') {
$post->{post_display_is_flat} = 1;
}
else {
$post->{post_display_is_threaded} = 1;
}
}
attachments($posts);
$posts;
}
# Takes a hash ref and sets $hash->{post_attachments} to an array ref of hash refs.
# The hash refs are the attachments of the post. If the post field "post_has_attachments"
# is not set, this subroutine does nothing.
sub attachments {
my $posts = ref $_[0] eq 'ARRAY' ? shift : [shift];
my %attachments;
for my $i (0 .. $#$posts) {
my $post = $posts->[$i];
$post->{post_has_attachments} or next;
push @{$attachments{$post->{post_id}}}, $i;
}
return unless keys %attachments;
my $sth = $DB->table('PostAttachment')->select({ post_id_fk => [keys %attachments] });
my $num_attachments = 0;
while (my $attachment = $sth->fetchrow_hashref) {
$attachment->{postatt_filename_escaped} = escape_string($IN->escape($attachment->{postatt_filename}));
my @i = @{$attachments{$attachment->{post_id_fk}}};
for my $i (@i) {
push @{$posts->[$i]->{post_attachments}}, $attachment;
$posts->[$i]->{post_num_attachments}++;
}
}
return;
}
# Takes two arguments: A scalar reference to a non-normalized post_message
# value, and the normalized Post,User hash it came from. Returns nothing.
$COMPILE{plain_text} = __LINE__ . <<'END_OF_SUB';
sub plain_text {
my ($str, $post) = @_;
convert_signature($str, \$post->{user_signature});
$$str =~ s/
/\n/g if $post->{post_style} >= 2;
$$str =~ s/<.*?>//g if $post->{post_style} >= 2;
$$str =~ s/\[(\s*([^\s\]]*).*?\s*)\]/if (exists $CFG->{markup_tags}->{lc $2} or exists $CFG->{markup_tags}->{lc($2) . "()"}) { "" } elsif (substr($1, 0, 1) eq ".") { "[" . substr($1, 1) . "]" } else { "[$1]" }/eg if $post->{post_style} % 2;
return;
}
END_OF_SUB
$COMPILE{delete} = __LINE__ . <<'END_OF_SUB';
sub delete {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('post');
$post_id and my $post = $DB->table('Post' => 'User')->select(left_join => { post_id => $post_id })->fetchrow_hashref
or return($page->{failed} => {
error => GForum::language('POST_DOES_NOT_EXIST')
}
);
my $forum = $DB->table('Forum', 'Category')->select({ forum_id => $post->{forum_id_fk} })->fetchrow_hashref;
unless ($USER->{user_forum_permission} >= FORUM_PERM_MODERATOR
or ($USER->{user_id} == $post->{user_id_fk}
and
$forum->{forum_allow_user_edit} >= 2 # 2 is delete, 3 is edit & delete, but 0 and 1 do not allow deleting
and
(!$forum->{forum_edit_timeout} or ($post->{post_time} + $forum->{forum_edit_timeout} * 60) > time)
)
) {
$GForum::Template::VARS{permission_denied_reason} = GForum::language('POST_EDIT_TIME_EXPIRED');
return GForum::do_func('permission_denied');
}
normalize($post);
require GForum::Forum;
GForum::Forum::normalize($forum);
if ($forum->{forum_hard_delete} == 1 or $forum->{forum_hard_delete} == 2 and not $post->{post_replies}) {
$DB->table('Post')->delete($post_id);
# Attachments are deleted by GT::SQL (PostAttachment has a foreign key to post_id)
}
else {
$DB->table('Post')->update({ post_deleted => 1, post_deleted_by => $USER->{user_username}, post_deleted_time => time }, { post_id => $post_id });
# Attachments have to be deleted
$DB->table('PostAttachment')->delete({ post_id_fk => $post_id });
}
return(
$page->{delete} => {
%$post,
%$forum
}
);
}
END_OF_SUB
# Just like delete above, except that this is meant for moderators only. It
# deletes the post and all replies, regardless of the forum_hard_delete setting.
$COMPILE{remove} = __LINE__ . <<'END_OF_SUB';
sub remove {
shift;
my ($do, $func) = @_;
my $page = $func->{page};
my $post_id = $IN->param('post');
$post_id and my $post = $DB->table('Post' => 'User')->select(left_join => { post_id => $post_id })->fetchrow_hashref
or return($page->{failed} => {
error => GForum::language('POST_DOES_NOT_EXIST')
}
);
my $forum = $DB->table('Forum', 'Category')->select({ forum_id => $post->{forum_id_fk} })->fetchrow_hashref;
unless ($USER->{user_forum_permission} >= FORUM_PERM_MODERATOR) {
$GForum::Template::VARS{permission_denied_reason} = GForum::language('POST_REMOVE_NOT_MODERATOR');
return GForum::do_func('permission_denied');
}
normalize($post);
require GForum::Forum;
GForum::Forum::normalize($forum);
$DB->table('Post')->delete($post_id);
return(
$page->{delete} => {
%$post,
%$forum
}
);
}
END_OF_SUB
# This function is called from the admin templates
$COMPILE{delete_old} = __LINE__ . <<'END_OF_SUB';
sub delete_old {
my $num_days = shift or return;
my $cutoff = time - 24 * 60 * 60 * $num_days;
my $cond = GT::SQL::Condition->new(
post_latest_reply => '>=' => (2_000_000_000 - $cutoff),
post_keep => '=' => 0,
post_root_id => '=' => 0
);
my $deleted = $DB->table('Post')->delete($cond);
$deleted or die "$deleted: $GT::SQL::error";
return { posts_deleted => 0 + $deleted }
}
END_OF_SUB
$COMPILE{count_old} = __LINE__ . <<'END_OF_SUB';
sub count_old {
my $num_days = shift or return;
my $cutoff = time - 24 * 60 * 60 * $num_days;
my $cond = GT::SQL::Condition->new(
post_latest_reply => '>=' => (2_000_000_000 - $cutoff),
post_keep => '=' => 0
);
my $count = $DB->table('Post')->count($cond);
die $GT::SQL::error if not defined $count;
return $count;
}
END_OF_SUB
# This must be called either from the admin
$COMPILE{reindex} = __LINE__ . <<'END_OF_SUB';
sub reindex {
my $hires = eval "require Time::HiRes";
my $s = $hires ? Time::HiRes::time() : time;
my $t = localtime;
my $old_autoflush = $|;
$| = 1 if not $old_autoflush;
my $html = 1 if $ENV{REQUEST_METHOD};
print "Reindexing Gossamer Forum database ...\n\n" if not $html;
print "Started at $t.\n\nIndexing Post database ...\n\n";
my $post = $DB->table('Post');
my $total = $post->count({ post_deleted => 0 });
my $weights = $post->weight || {};
my $found;
for (keys %$weights) {
$found = 1 if $weights->{$_} > 0;
}
unless ($found) {
print "" if $html;
print "No search weights have been set, aborting!\n\n";
print "" if $html;
return;
}
print "$total posts.\n";
$post->reindex({ tick => 250, max => 1000, cond => { post_deleted => 0 } });
printf "\nDone! (%.2f s)\n\n", ($hires ? Time::HiRes::time() : time) - $s;
$| = 0 if not $old_autoflush;
return;
}
END_OF_SUB
# Returs Icon and IconAlt template tags. Icon is something like
# "hot_new_with_new_replies.gif" and IconAlt is to alt tag to be used with the
# image. This is also going to call GForum::Template::store_gvars with the
# following, depening on the icon requested:
# legend_hot - any hot post
# legend_new - any new post
# legend_replies - any post with replies
# legend_single - any post without replies
# legend_new_replies - any post with new replies
# legend_new_new_replies - any new post with new replies
$COMPILE{status_icon} = __LINE__ . <<'END_OF_SUB';
sub status_icon {
my ($thread_hot, $post_new, $post_replies, $new_replies) = @_;
my $ret;
$ret->{Icon} = '';
my $this_is_new;
if ($thread_hot) {
$ret->{Icon} .= "hot_";
GForum::Template::store_gvars(legend_hot => 1);
}
if ($post_new) {
$ret->{Icon} .= "new_";
$this_is_new = 1;
GForum::Template::store_gvars(legend_new => 1);
}
if ($post_replies) {
GForum::Template::store_gvars(legend_replies => 1);
if ($new_replies) {
GForum::Template::store_gvars(legend_new_replies => 1);
if ($this_is_new) {
GForum::Template::store_gvars(legend_new_new_replies => 1);
}
$ret->{Icon} .= "with_new_replies";
}
else {
$ret->{Icon} .= "with_replies";
}
}
else {
GForum::Template::store_gvars(legend_single => 1);
$ret->{Icon} .= "no_replies";
}
$ret->{IconAlt} = GForum::language("POSTICON_$ret->{Icon}");
$ret->{Icon} .= ".gif";
$ret;
}
END_OF_SUB
1;