# # Recents # # 2005/03/27 0.01 First version # 2005/06/23 0.02 Update for archive context # 2005/10/05 1.01 Update for Movable Type 3.2 # # Copyright(c) by H.Fujimoto # package MT::Plugin::Recents; use strict; use MT; use MT::Template::Context; use MT::Plugin; use MT::TBPing; use MT::Trackback; use MT::Comment; use MT::Entry; # show plugin information to main menu eval("use Storable;"); if (!$@ && MT->can('add_plugin')) { my $plugin = MT::Plugin->new; if (MT->version_number >= 3.2) { $plugin->name('Recents'); $plugin->version('1.01'); $plugin->author_name('Hajime Fujimoto'); $plugin->author_link('http://www.h-fj.com/blog/'); } else { $plugin->name('Recents 1.01'); } $plugin->description('Get recent pings/comments with entry.'); $plugin->doc_link('http://www.h-fj.com/blog/archives/2005/06/23-000707.php'); MT->add_plugin($plugin); } # add container tag MT::Template::Context->add_container_tag(PingsRecent => \&pings_recent); MT::Template::Context->add_container_tag(CommentsRecent => \&comments_recent); MT::Template::Context->add_conditional_tag(PingsRecentIfEntry => \&recent_if_entry); MT::Template::Context->add_conditional_tag(PingsRecentIfPing => \&recent_if_ping); MT::Template::Context->add_conditional_tag(PingsRecentHeader => \&recent_header); MT::Template::Context->add_conditional_tag(PingsRecentFooter => \&recent_footer); MT::Template::Context->add_conditional_tag(PingsRecentEntryHeader => \&recent_entry_header); MT::Template::Context->add_conditional_tag(PingsRecentEntryFooter => \&recent_entry_footer); MT::Template::Context->add_conditional_tag(CommentsRecentIfEntry => \&recent_if_entry); MT::Template::Context->add_conditional_tag(CommentsRecentIfComment => \&recent_if_comment); MT::Template::Context->add_conditional_tag(CommentsRecentHeader => \&recent_header); MT::Template::Context->add_conditional_tag(CommentsRecentFooter => \&recent_footer); MT::Template::Context->add_conditional_tag(CommentsRecentEntryHeader => \&recent_entry_header); MT::Template::Context->add_conditional_tag(CommentsRecentEntryFooter => \&recent_entry_footer); # main sub pings_recent { my ($ctx, $args) = @_; my $tokens = $ctx->stash('tokens'); my $builder = $ctx->stash('builder'); my $res = ''; my @recent_entries = (); my @recent_pings = (); my %recent_ptr = (); my $ping_ctr = 0; my $entry_ctr = 0; my ($lastn, $force, $mode, $trackback, $entry); my ($entry_id, $entry_ptr, $ping_ptr); my ($entry_sort_order, $ping_sort_order); my ($category, $date_start, $date_end); my (%terms, %args); # get attributes $lastn = $args->{'lastn'} or $lastn = 0; $force = ($args->{'mode'} eq 'force'); $mode = $args->{'mode'} or $mode = 'pinged_date'; $entry_sort_order = $args->{'entry_sort_order'} or $entry_sort_order = "descend"; $ping_sort_order = $args->{'ping_sort_order'} or $ping_sort_order = "descend"; # get template context $category = $ctx->stash('archive_category') || $ctx->stash('category'); $date_start = $ctx->{'current_timestamp'}; $date_end = $ctx->{'current_timestamp_end'}; # get recently pings $terms{blog_id} = $ctx->stash('blog_id'); $args{sort} = 'created_on'; $args{direction} = 'descend'; if ($date_start && $date_end && $mode eq 'pinged_date' && !$force) { $args{range} = { created_on => 1 }; $terms{created_on} = [ $date_start, $date_end ]; } if (MT->version_number >= 3.2) { $terms{visible} = 1; } my $iter = MT::TBPing->load_iter(\%terms, \%args); # loop each MT::TBPing object while (my $ping = $iter->()) { # load MT::Trackback object and get entry_id $trackback = MT::Trackback->load($ping->tb_id); $entry_id = $trackback->entry_id; # skip ping to category next if ($entry_id == 0); # load pinged entry $entry = MT::Entry->load($entry_id); # skip ping to not released entry next if ($entry->status != MT::Entry::RELEASE()); # skip ping to other category in category context next if ($category && !$force && $category->id != $entry->category->id); # skip ping to not in date range in daily context next if ($date_start && $date_end && $mode ne 'pinged_date' && !$force && ($entry->created_on < $date_start || $entry->created_on > $date_end)); # set ping and entry information if (!defined($recent_ptr{$entry->id})) { $entry_ptr = $entry_ctr; $recent_ptr{$entry->id} = $entry_ptr; push @recent_entries, $entry; $entry_ctr++; } else { $entry_ptr = $recent_ptr{$entry->id}; } if ($ping_sort_order eq 'ascend') { unshift @{$recent_pings[$entry_ptr]}, $ping; } else { push @{$recent_pings[$entry_ptr]}, $ping; } # when listed lastn pings, exit loop $ping_ctr++; last if ($ping_ctr == $lastn); } # if entry_sort_order is ascend, reverse array if ($entry_sort_order eq 'ascend') { @recent_entries = reverse @recent_entries; @recent_pings = reverse @recent_pings; } # backup stash('entry') my $entrybackup = $ctx->stash('entry'); # out recent pings and entries $entry_ptr = 0; foreach my $entry (@recent_entries) { $ctx->stash('entry', $entry); $ctx->stash('objtype', 'entry'); local $ctx->{current_timestamp} = $entry->created_on; $ctx->stash('is_first_entry', !$entry_ptr); if ($entry_ptr == $entry_ctr - 1) { $ctx->stash('is_last_entry', 1); } else { $ctx->stash('is_last_entry', 0); } defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; $ping_ptr = 0; $ping_ctr = scalar(@{$recent_pings[$entry_ptr]}); foreach my $ping (@{$recent_pings[$entry_ptr]}) { $ctx->stash('is_first', !$ping_ptr); $ctx->stash('ping', $ping); $ctx->stash('objtype', 'ping'); local $ctx->{current_timestamp} = $ping->created_on; if ($ping_ptr == $ping_ctr - 1) { $ctx->stash('is_last', 1); } else { $ctx->stash('is_last', 0); } defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; $ping_ptr++; } $entry_ptr++; } # restore stash('entry') $ctx->stash('entry', $entrybackup); $res; } sub comments_recent { my ($ctx, $args) = @_; my $tokens = $ctx->stash('tokens'); my $builder = $ctx->stash('builder'); my $res = ''; my @recent_entries = (); my @recent_comments = (); my %recent_ptr = (); my $comment_ctr = 0; my $entry_ctr = 0; my ($lastn, $force, $mode, $trackback, $entry); my ($entry_id, $entry_ptr, $comment_ptr); my ($entry_sort_order, $comment_sort_order); my ($category, $date_start, $date_end); my (%terms, %args); # get attribute $lastn = $args->{'lastn'} or $lastn = 0; $force = ($args->{'mode'} eq 'force'); $mode = $args->{'mode'} or $mode = 'commented_date'; $entry_sort_order = $args->{'entry_sort_order'} or $entry_sort_order = "descend"; $comment_sort_order = $args->{'comment_sort_order'} or $comment_sort_order = $ctx->stash('blog')->sort_order_comments; # get template context $category = $ctx->stash('archive_category') || $ctx->stash('category'); $date_start = $ctx->{'current_timestamp'}; $date_end = $ctx->{'current_timestamp_end'}; # get recently comments $terms{blog_id} = $ctx->stash('blog_id'); $terms{visible} = 1; $args{sort} = 'created_on'; $args{direction} = 'descend'; if ($date_start && $date_end && $mode eq 'commented_date' && !$force) { $args{range} = { created_on => 1 }; $terms{created_on} = [ $date_start, $date_end ]; } my $iter = MT::Comment->load_iter(\%terms, \%args); # loop each MT::Comment object while (my $comment = $iter->()) { # load commented entry $entry_id = $comment->entry_id; $entry = MT::Entry->load($entry_id); # skip comment to not released entry next if ($entry->status != MT::Entry::RELEASE()); # skip comment to other category in category context next if ($category && !$force && $category->id != $entry->category->id); # skip comment to not in date range in daily context next if ($date_start && $date_end && $mode ne 'commented_date' && !$force && ($entry->created_on < $date_start || $entry->created_on > $date_end)); # set comment and entry information if (!defined($recent_ptr{$entry->id})) { $entry_ptr = $entry_ctr; $recent_ptr{$entry->id} = $entry_ptr; push @recent_entries, $entry; $entry_ctr++; } else { $entry_ptr = $recent_ptr{$entry->id}; } if ($comment_sort_order eq 'ascend') { unshift @{$recent_comments[$entry_ptr]}, $comment; } else { push @{$recent_comments[$entry_ptr]}, $comment; } # when listed lastn comments, exit loop $comment_ctr++; last if ($comment_ctr == $lastn); } # if entry_sort_order is ascend, reverse array if ($entry_sort_order eq 'ascend') { @recent_entries = reverse @recent_entries; @recent_comments = reverse @recent_comments; } # backup stash('entry') my $entrybackup = $ctx->stash('entry'); # out recent comments and entries $entry_ptr = 0; foreach my $entry (@recent_entries) { $ctx->stash('entry', $entry); $ctx->stash('objtype', 'entry'); local $ctx->{current_timestamp} = $entry->created_on; $ctx->stash('is_first_entry', !$entry_ptr); if ($entry_ptr == $entry_ctr - 1) { $ctx->stash('is_last_entry', 1); } else { $ctx->stash('is_last_entry', 0); } defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; $comment_ptr = 0; $comment_ctr = scalar(@{$recent_comments[$entry_ptr]}); foreach my $comment (@{$recent_comments[$entry_ptr]}) { $ctx->stash('is_first', !$comment_ptr); $ctx->stash('comment', $comment); $ctx->stash('objtype', 'comment'); local $ctx->{current_timestamp} = $comment->created_on; if ($comment_ptr == $comment_ctr - 1) { $ctx->stash('is_last', 1); } else { $ctx->stash('is_last', 0); } defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $res .= $out; $comment_ptr++; } $entry_ptr++; } # restore stash('entry') $ctx->stash('entry', $entrybackup); $res; } sub recent_if_entry { my ($ctx, $args) = @_; $ctx->stash('objtype') eq 'entry'; } sub recent_if_ping { my ($ctx, $args) = @_; $ctx->stash('objtype') eq 'ping'; } sub recent_if_comment { my ($ctx, $args) = @_; $ctx->stash('objtype') eq 'comment'; } sub recent_header { my ($ctx, $args) = @_; $ctx->stash('is_first'); } sub recent_footer { my ($ctx, $args) = @_; $ctx->stash('is_last'); } sub recent_entry_header { my ($ctx, $args) = @_; $ctx->stash('is_first_entry'); } sub recent_entry_footer { my ($ctx, $args) = @_; $ctx->stash('is_last_entry'); } 1;