mourningdove/cgi-bin/LJ/NotificationItem.pm

243 lines
5.9 KiB
Perl
Raw Normal View History

2026-05-24 01:03:05 +00:00
# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.
# This is a class representing a notification that came out of an
# LJ::NotificationInbox. You can tell it to mark itself as
# read/unread, delete it, and get the event that it contains out of
# it.
# Mischa Spiegelmock, 05/2006
package LJ::NotificationItem;
use strict;
use warnings;
no warnings "redefine";
use LJ::NotificationInbox;
use LJ::Event;
use Carp qw(croak);
*new = \&instance;
# parameters: user, notification inbox id
sub instance {
my ( $class, $u, $qid ) = @_;
my $singletonkey = $qid;
$u->{_inbox_items} ||= {};
return $u->{_inbox_items}->{$singletonkey} if $u->{_inbox_items}->{$singletonkey};
my $self = {
userid => $u->id,
qid => $qid,
state => undef,
event => undef,
when => undef,
_loaded => 0,
};
$u->{_inbox_items}->{$singletonkey} = $self;
return bless $self, $class;
}
# returns whose notification this is
*u = \&owner;
sub owner { LJ::load_userid( $_[0]->{userid} ) }
# returns this item's id in the notification queue
sub qid { $_[0]->{qid} }
# returns true if this item really exists
sub valid {
my $self = shift;
return undef unless $self->u && $self->qid;
$self->_load unless $self->{_loaded};
return $self->event;
}
# returns title of this item
sub title {
my $self = shift;
return "(Invalid event)" unless $self->event;
my %opts = @_;
my $mode = delete $opts{mode};
croak "Too many args passed to NotificationItem->as_html" if %opts;
$mode = "html" unless $mode;
if ( $mode eq "html" ) {
return eval { $self->event->as_html( $self->u ) } || $@;
}
}
# returns contents of this item for user u
sub as_html {
my $self = shift;
croak "Too many args passed to NotificationItem->as_html" if scalar @_;
return "(Invalid event)" unless $self->event;
return eval { $self->event->content( $self->u ) } || $@;
}
sub as_html_summary {
my $self = shift;
croak "Too many args passed to NotificationItem->as_html_summary" if scalar @_;
return "(Invalid event)" unless $self->event;
return eval { $self->event->content_summary( $self->u ) } || $@;
}
# returns the event that this item refers to
sub event {
my $self = shift;
$self->_load unless $self->{_loaded};
return $self->{event};
}
# loads this item
sub _load {
my $self = shift;
my $qid = $self->qid;
my $u = $self->owner;
return if $self->{_loaded};
# load info for all the currently instantiated singletons
# get current singleton qids
$u->{_inbox_items} ||= {};
my @qids = map { $_->qid } values %{ $u->{_inbox_items} };
my $bind = join( ',', map { '?' } @qids );
my $sth = $u->prepare( "SELECT userid, qid, journalid, etypeid, arg1, arg2, state, createtime "
. "FROM notifyqueue WHERE userid=? AND qid IN ($bind)" );
$sth->execute( $u->id, @qids );
die $sth->errstr if $sth->err;
my @items;
while ( my $row = $sth->fetchrow_hashref ) {
my $qid = $row->{qid} or next;
my $singleton = $u->{_inbox_items}->{$qid} or next;
push @items, $singleton->absorb_row($row);
}
}
# fills in a skeleton item from a database row hashref
sub absorb_row {
my ( $self, $row ) = @_;
$self->{_loaded} = 1;
$self->{state} = $row->{state};
$self->{when} = $row->{createtime};
my $evt = LJ::Event->new_from_raw_params( $row->{etypeid}, $row->{journalid}, $row->{arg1},
$row->{arg2} );
$self->{event} = $evt;
return $self;
}
# returns when this event happened (or got put in the inbox)
sub when_unixtime {
my $self = shift;
$self->_load unless $self->{_loaded};
return $self->{when};
}
# returns the state of this item
sub _state {
my $self = shift;
$self->_load unless $self->{_loaded};
return $self->{state};
}
# returns if this event is marked as read
sub read {
return 0 unless defined $_[0]->_state;
return $_[0]->_state eq 'R';
}
# returns if this event is marked as unread
sub unread {
return 0 unless defined $_[0]->_state;
return $_[0]->_state eq 'N';
}
# delete this item from its inbox
sub delete {
my $self = shift;
return unless $self->owner;
my $inbox = $self->owner->notification_inbox;
# delete from the inbox so the inbox stays in sync
my $ret = $inbox->delete_from_queue($self);
%$self = ();
return $ret;
}
# mark this item as read
sub mark_read {
my $self = shift;
# do nothing if it's already marked as read
return if $self->read;
$self->_set_state('R');
}
# mark this item as read
sub mark_unread {
my $self = shift;
# do nothing if it's already marked as unread
return if $self->unread;
$self->_set_state('N');
}
# sets the state of this item
sub _set_state {
my ( $self, $state ) = @_;
$self->owner->do( "UPDATE notifyqueue SET state=? WHERE userid=? AND qid=?",
undef, $state, $self->owner->id, $self->qid )
or die $self->owner->errstr;
$self->{state} = $state;
# expire unread cache
my $userid = $self->u->id;
my $memkey = [ $userid, "inbox:newct:${userid}" ];
LJ::MemCache::delete($memkey);
}
# JSON output implementation for NotificationItem objects
sub TO_JSON {
my $self = shift;
my $json = {
title => $self->title,
content => $self->as_html,
unread => $self->unread,
timestamp => $self->when_unixtime
};
}