/usr/local/CPAN/Parley/Parley/ResultSet/Thread.pm
package Parley::ResultSet::Thread;
# vim: ts=8 sts=4 et sw=4 sr sta
use strict;
use warnings;
use Parley::Version; our $VERSION = $Parley::VERSION;
use base 'DBIx::Class::ResultSet';
# This is slightly complicated; the way we find the last post a user has seen
# in a thread is:
#
# - If there is a thread_view entry for person-thread then find the last post
# made on or before that time
# - If there is no thread_view entry, then the user has never seen the thread
# before, in which case the last post viewed is considered to be the
# first post in the thread
sub last_post_viewed_in_thread {
my ($self, $person, $thread) = @_;
my ($last_viewed, $last_post) = @_;
if (not defined $thread) {
die "no thread defined";
}
my $schema = $self->result_source()->schema();
# we need to be careful that we haven't deleted/hidden the post that
# matches the exact timestamp of last_viewed for a thread - this is why we
# use <= and not ==, since we can just return the latest undeleted post
# get the entry (if any) for person-thread from the thread_view table
$last_viewed = $schema->resultset('ThreadView')->find(
{
person_id => $person->id(),
thread_id => $thread->id(),
}
);
# if we don't have a $last_viewed, then return the thread's first post
if (not defined $last_viewed) {
warn "thread has never been viewed - returning first post in thread";
# get all the posts in the thread, oldest first
my $posts_in_thread = $schema->resultset('Post')->search(
{
thread_id => $thread->id(),
},
{
rows => 1,
order_by => [\'created ASC'],
}
);
# set the first post
$last_post = $posts_in_thread->first();
}
# otherwise, find the most recent post made on or before the timestamp in
# $last_viewed
else {
warn q{looking for a post on or before } . $last_viewed->timestamp();
# get a list of posts created on or before our last-post time, newest
# first
my $list_of_posts = $schema->resultset('Post')->search(
{
created => {
'<=',
DateTime::Format::Pg->format_datetime(
$last_viewed->timestamp()
)
},
thread_id => $thread->id(),
},
{
rows => 1,
order_by => [\'created DESC'],
}
);
# the most recent post is the first (and only) post in our list
$last_post = $list_of_posts->first();
}
# we should now have a Post object in $last_post
if (not defined $last_post) {
warn q{$last_post is undefined in last_post_viewed_in_thread()};
return;
}
# return the last post ..
return $last_post;
}
sub recent {
my ($resultset, $c) = @_;
my ($thread_list, $where, @join);
# page to show - either a param, or show the first
$c->stash->{current_page}= $c->request->param('page') || 1;
# always want to join with last_post table
@join = qw(last_post);
# only search active forums
$where->{'me.active'} = 1;
# if we're only interested in a given forum
if (defined $c->_current_forum()) {
$where->{forum} = $c->_current_forum->id();
}
$resultset->search(
$where,
{
join => \@join,
order_by => [\'last_post.created DESC'],
rows => $c->config->{threads_per_page},
page => $c->stash->{current_page},
prefetch => [
{'creator' => 'authentication'},
{'last_post' => 'creator'},
'forum',
],
}
);
}
sub record_from_id {
my ($resultsource, $thread_id) = @_;
my ($rs);
$rs = $resultsource->find(
{
'me.id' => $thread_id,
},
{
prefetch => [
{ 'forum' => 'last_post' },
'creator',
'last_post',
]
}
);
return $rs;
}
1;