LJSUP-17669: Login.bml form refactoring
[livejournal.git] / cgi-bin / LJ / NotificationArchive.pm
blob1f28a72ab45fdfc1584750107f98435e53d22e90
1 # This package is for managing a queue of archived notifications
2 # for a user.
3 # Henry Lyne 20070604
5 package LJ::NotificationArchive;
7 use strict;
8 use Carp qw(croak);
9 use Class::Autouse qw (LJ::NotificationItem LJ::Event);
11 *new = \&instance;
13 my %singletons = ();
15 # constructor takes a $u
16 sub instance {
17 my ($class, $u) = @_;
19 croak "Invalid args to construct LJ::NotificationArchive" unless $class && $u;
20 croak "Invalid user" unless LJ::isu($u);
22 return $singletons{$u->{userid}} if $singletons{$u->{userid}};
24 my $self = {
25 uid => $u->userid,
26 count => undef, # defined once ->count is loaded/cached
27 items => undef,
30 $singletons{$u->{userid}} = $self;
32 return bless $self, $class;
35 # returns the user object associated with this queue
36 sub u {
37 my $self = shift;
38 return LJ::load_userid($self->{uid});
41 # returns all non-deleted Event objects for this user
42 # in a hashref of {queueid => event}
43 # optional arg: daysold = how many days back to retrieve notifications for
44 sub notifications {
45 my $self = shift;
46 my $daysold = shift;
48 croak "notifications is an object method"
49 unless (ref $self) eq __PACKAGE__;
51 return $self->_load($daysold);
54 # Returns a list of LJ::NotificationItems in this queue.
55 sub items {
56 my $self = shift;
58 croak "items is an object method"
59 unless (ref $self) eq __PACKAGE__;
61 return @{$self->{items}} if defined $self->{items};
63 my @qids = $self->_load;
65 my @items = ();
66 foreach my $qid (@qids) {
67 push @items, LJ::NotificationItem->new($self->u, $qid);
70 $self->{items} = \@items;
72 return @items;
76 # load the events in this queue
77 sub _load {
78 my $self = shift;
80 return $self->{events} if $self->{loaded};
82 my $u = $self->u
83 or die "No user object";
85 # is it memcached?
86 my $qids;
87 $qids = LJ::MemCache::get($self->_memkey) and return @$qids;
89 # State of 'D' means Deleted
90 my $sth = $u->prepare
91 ("SELECT userid, qid, journalid, etypeid, arg1, arg2, state, createtime " .
92 "FROM notifyarchive WHERE userid=? AND state!='D'");
93 $sth->execute($u->{userid});
94 die $sth->errstr if $sth->err;
96 my @items = ();
97 while (my $row = $sth->fetchrow_hashref) {
98 my $qid = $row->{qid};
100 # load this item into process cache so it's ready to go
101 my $qitem = LJ::NotificationItem->new($u, $qid);
102 $qitem->absorb_row($row);
104 push @items, $qitem;
107 # sort based on create time
108 @items = sort { $a->when_unixtime <=> $b->when_unixtime } @items;
110 # get sorted list of ids
111 my @item_ids = map { $_->qid } @items;
113 LJ::MemCache::set($self->_memkey, \@item_ids);
115 return @item_ids;
118 sub _memkey {
119 my $self = shift;
120 my $userid = $self->{uid};
121 return [$userid, "inbox:archive:$userid"];
124 # deletes an Event that is queued for this user
125 # args: Queue ID to remove from queue
126 sub delete_from_queue {
127 my ($self, $qid) = @_;
129 croak "delete_from_queue is an object method"
130 unless (ref $self) eq __PACKAGE__;
132 croak "no queueid passed to delete_from_queue" unless int($qid);
134 my $u = $self->u
135 or die "No user object";
137 $self->_load;
139 # if this event was returned from our queue we should have
140 # its qid stored in our events hashref
141 delete $self->{events}->{$qid};
143 $u->do("UPDATE notifyqueue SET state='D' WHERE qid=?", undef, $qid);
144 die $u->errstr if $u->err;
146 # invalidate caches
147 $self->expire_cache;
149 return 1;
152 sub expire_cache {
153 my $self = shift;
155 $self->{count} = undef;
156 $self->{items} = undef;
158 LJ::MemCache::delete($self->_memkey);
161 # This will enqueue an event object
162 # Returns the queue id
163 sub enqueue {
164 my ($self, %opts) = @_;
166 my $evt = delete $opts{event};
167 croak "No event" unless $evt;
168 croak "Extra args passed to enqueue" if %opts;
170 my $u = $self->u or die "No user";
172 # get a qid
173 my $qid = LJ::alloc_user_counter($u, 'Q')
174 or die "Could not alloc new queue ID";
176 my %item = (qid => $qid,
177 userid => $u->{userid},
178 journalid => $evt->u->{userid},
179 etypeid => $evt->etypeid,
180 arg1 => $evt->arg1,
181 arg2 => $evt->arg2,
182 state => ' ',
183 createtime => time());
185 # write to archive table
186 $u->do("INSERT INTO notifyarchive (". join(",", keys %item) .") VALUES (" .
187 join(",", map { '?' } values %item) . ")", undef, values %item)
188 or die $u->errstr;
190 $self->{events}->{$qid} = $evt;
192 return $qid;