[livejournal] r19465: LJSUP-9270: Creare RSS feed for friends ...
Committer: amyshkin
LJSUP-9270: Creare RSS feed for friends pageU trunk/bin/upgrading/en.dat U trunk/cgi-bin/LJ/Entry.pm U trunk/cgi-bin/ljfeed.pl U trunk/cgi-bin/ljlib.pl
Modified: trunk/bin/upgrading/en.dat
===================================================================
--- trunk/bin/upgrading/en.dat 2011-07-12 06:24:19 UTC (rev 19464)
+++ trunk/bin/upgrading/en.dat 2011-07-12 06:57:34 UTC (rev 19465)
@@ -2704,6 +2704,8 @@
feeds.text=Apparently there's good content outside of LJ? We'll let you add [[link]] to your Friends page so you never have to leave.
+feeds.title.friends=friends page feed
+
gender.female|staleness=1
gender.female=Female
Modified: trunk/cgi-bin/LJ/Entry.pm
===================================================================
--- trunk/cgi-bin/LJ/Entry.pm 2011-07-12 06:24:19 UTC (rev 19464)
+++ trunk/cgi-bin/LJ/Entry.pm 2011-07-12 06:57:34 UTC (rev 19465)
@@ -78,6 +78,7 @@
$self->{anum} = delete $opts{anum};
$self->{ditemid} = delete $opts{ditemid};
$self->{jitemid} = delete $opts{jitemid};
+ $self->{rlogtime}= delete $opts{rlogtime};
# make arguments numeric
for my $f (qw(ditemid jitemid anum)) {
@@ -90,7 +91,7 @@
croak("Unknown parameters: " . join(", ", keys %opts))
if %opts;
- if ($self->{ditemid}) {
+ if ( $self->{ditemid} ) {
$self->{anum} = $self->{ditemid} & 255;
$self->{jitemid} = int($self->{ditemid} / 256);
}
@@ -108,6 +109,8 @@
__PACKAGE__->preload_rows([ $self ]);
return undef if $anum and $anum != $self->{anum}; # incorrect anum -> 'no such entry'
+ $self->{ditemid} = $self->{jitemid} * 256 + $self->{anum};
+
# save the singleton if it doesn't exist
$singletons{$journalid}->{$jitemid} = $self;
@@ -206,12 +209,12 @@
my $self = shift;
my %opts = @_;
my %args = %opts; # used later
- my $u = $self->{u};
- my $view = delete $opts{view};
+ my $u = $self->{u};
+ my $view = delete $opts{view};
my $anchor = delete $opts{anchor};
- my $mode = delete $opts{mode};
- my $style = delete $opts{style};
- my $nc = delete $opts{nc};
+ my $mode = delete $opts{mode};
+ my $style = delete $opts{style};
+ my $nc = delete $opts{nc};
croak "Unknown args passed to url: " . join(",", keys %opts)
if %opts;
@@ -430,6 +433,7 @@
sub prop {
my ($self, $prop) = @_;
$self->_load_props unless $self->{_loaded_props};
+ return $self->{props} unless $prop;
return $self->{props}{$prop};
}
@@ -2174,8 +2178,7 @@
# des-:
# returns:
# </LJFUNC>
-sub load_log_props2
-{
+sub load_log_props2 {
my $db = isdb($_[0]) ? shift @_ : undef;
my ($uuserid, $listref, $hashref) = @_;
@@ -2186,50 +2189,57 @@
my %needrc;
my %rc;
my @memkeys;
- foreach (@$listref) {
- my $id = $_+0;
+
+ foreach ( @$listref ) {
+ my $id = $_ + 0;
$needprops{$id} = 1;
- $needrc{$id} = 1;
+ $needrc{$id} = 1;
push @memkeys, [$userid, "logprop:$userid:$id"];
push @memkeys, LJ::Entry::reply_count_memkey($userid, $id);
}
+
return unless %needprops || %needrc;
my $mem = LJ::MemCache::get_multi(@memkeys) || {};
- while (my ($k, $v) = each %$mem) {
+
+ while ( my ($k, $v) = each %$mem ) {
next unless $k =~ /(\w+):(\d+):(\d+)/;
- if ($1 eq 'logprop') {
+
+ if ( $1 eq 'logprop' ) {
next unless ref $v eq "HASH";
delete $needprops{$3};
$hashref->{$3} = $v;
}
- if ($1 eq 'rp') {
+
+ if ( $1 eq 'rp' ) {
delete $needrc{$3};
$rc{$3} = int($v); # change possible "0 " (true) to "0" (false)
}
}
- foreach (keys %rc) {
+ foreach ( keys %rc ) {
$hashref->{$_}{'replycount'} = $rc{$_};
}
return unless %needprops || %needrc;
- unless ($db) {
+ unless ( $db ) {
my $u = LJ::load_userid($userid);
$db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u);
return unless $db;
}
- if (%needprops) {
+ if ( %needprops ) {
LJ::load_props("log");
my $in = join(",", keys %needprops);
my $sth = $db->prepare("SELECT jitemid, propid, value FROM logprop2 ".
"WHERE journalid=? AND jitemid IN ($in)");
$sth->execute($userid);
+
while (my ($jitemid, $propid, $value) = $sth->fetchrow_array) {
$hashref->{$jitemid}->{$LJ::CACHE_PROPID{'log'}->{$propid}->{'name'}} = $value;
}
+
foreach my $id (keys %needprops) {
LJ::MemCache::set([$userid,"logprop:$userid:$id"], $hashref->{$id} || {});
}
@@ -2516,12 +2526,10 @@
# des-opts: Optional hashref of special options. NOW IGNORED (2005-09-14)
# des-jitemid: List of jitemids to retrieve the subject & text for.
# </LJFUNC>
-sub get_logtext2
-{
+sub get_logtext2 {
my $u = shift;
my $clusterid = $u->{'clusterid'};
- my $journalid = $u->{'userid'}+0;
-
+ my $journalid = $u->{'userid'} + 0;
my $opts = ref $_[0] ? shift : {}; # this is now ignored
# return structure.
@@ -2531,14 +2539,16 @@
# keep track of itemids we still need to load.
my %need;
my @mem_keys;
+
foreach (@_) {
- my $id = $_+0;
+ my $id = $_ + 0;
$need{$id} = 1;
- push @mem_keys, [$journalid,"logtext:$clusterid:$journalid:$id"];
+ push @mem_keys, [$journalid, "logtext:$clusterid:$journalid:$id"];
}
# pass 1: memcache
my $mem = LJ::MemCache::get_multi(@mem_keys) || {};
+
while (my ($k, $v) = each %$mem) {
next unless $v;
$k =~ /:(\d+):(\d+):(\d+)/;
@@ -2556,13 +2566,15 @@
my $sth = $db->prepare("SELECT jitemid, subject, event FROM logtext2 ".
"WHERE journalid=$journalid AND jitemid IN ($jitemid_in)");
$sth->execute;
+
while (my ($id, $subject, $event) = $sth->fetchrow_array) {
LJ::text_uncompress(\$event);
my $val = [ $subject, $event ];
$lt->{$id} = $val;
- LJ::MemCache::add([$journalid,"logtext:$clusterid:$journalid:$id"], $val);
+ LJ::MemCache::add([$journalid, "logtext:$clusterid:$journalid:$id"], $val);
delete $need{$id};
}
+
return $lt;
}
Modified: trunk/cgi-bin/ljfeed.pl
===================================================================
--- trunk/cgi-bin/ljfeed.pl 2011-07-12 06:24:19 UTC (rev 19464)
+++ trunk/cgi-bin/ljfeed.pl 2011-07-12 06:57:34 UTC (rev 19465)
@@ -17,10 +17,10 @@
yadis => { handler => \&create_view_yadis, },
userpics => { handler => \&create_view_userpics, },
comments => { handler => \&create_view_comments, },
+ friends => { handler => \&create_view_rss, need_items => 1 },
);
-sub make_feed
-{
+sub make_feed {
my ($u, $remote, $opts) = @_;
$opts->{pathextra} =~ s!^/(\w+)!!;
@@ -36,8 +36,10 @@
my $allowed = 0;
my $remote_ip = LJ::get_remote_ip();
+
foreach my $block (@LJ::YANDEX_RSS_IP_BLOCKS) {
my $net = Net::Netmask->new($block);
+
next unless $net->match($remote_ip);
$allowed = 1;
last;
@@ -80,17 +82,17 @@
# if we do not want items for this view, just call out
$opts->{'contenttype'} = 'text/xml; charset='.$opts->{'saycharset'};
+
return $viewfunc->{handler}->($journalinfo, $u, $opts)
- unless ($viewfunc->{need_items});
+ unless $viewfunc->{need_items};
# for syndicated accounts, redirect to the syndication URL
# However, we only want to do this if the data we're returning
# is similar. (Not FOAF, for example)
if ($u->{'journaltype'} eq 'Y') {
my $synurl = $dbr->selectrow_array("SELECT synurl FROM syndicated WHERE userid=$u->{'userid'}");
- unless ($synurl) {
- return 'No syndication URL available.';
- }
+ return 'No syndication URL available.' unless $synurl;
+
$opts->{'redir'} = $synurl;
return undef;
}
@@ -98,10 +100,10 @@
my %FORM = LJ::Request->args;
## load the itemids
- my (@itemids, @items);
+ my (@itemids, @objs);
- # for consistency, we call ditemids "itemid" in user-facing settings
- my $ditemid = $FORM{itemid}+0;
+ # for consistency, we call ditemids "itemid" in user-facing settings
+ my $ditemid = $FORM{itemid} + 0;
if ($ditemid) {
my $entry = LJ::Entry->new($u, ditemid => $ditemid);
@@ -111,54 +113,57 @@
return undef;
}
- @itemids = $entry->jitemid;
-
- push @items, {
- itemid => $entry->jitemid,
- anum => $entry->anum,
- posterid => $entry->poster->id,
- security => $entry->security,
- alldatepart => LJ::TimeUtil->alldatepart_s2($entry->eventtime_mysql),
- };
- } else {
- @items = LJ::get_recent_items({
- 'clusterid' => $u->{'clusterid'},
- 'clustersource' => 'slave',
- 'remote' => $remote,
- 'userid' => $u->{'userid'},
- 'itemshow' => 25,
- 'order' => "logtime",
- 'tagids' => $opts->{tagids},
- 'tagmode' => $opts->{tagmode},
- 'itemids' => \@itemids,
- 'friendsview' => 1, # this returns rlogtimes
- 'dateformat' => "S2", # S2 format time format is easier
+ push @objs, $entry;
+ }
+ elsif ( $feedtype eq 'friends' ) {
+ LJ::get_friend_items({
+ 'u' => $u,
+ 'remote' => $remote,
+ 'itemshow' => 25,
+ 'dateformat' => 'S2',
+ 'itemids' => \@itemids,
+ 'entry_objects' => \@objs,
+ 'load_props' => 1,
+ 'load_text' => 1,
});
+ $journalinfo->{title} .= ' ' . LJ::Lang::ml('feeds.title.friends');
+ $journalinfo->{link} .= 'friends/';
}
+ else {
+ LJ::get_recent_items({
+ 'remote' => $remote,
+ 'userid' => $u->{'userid'},
+ 'itemshow' => 25,
+ 'order' => 'logtime',
+ 'tagids' => $opts->{tagids},
+ 'tagmode' => $opts->{tagmode},
+ 'itemids' => \@itemids,
+ 'friendsview' => 1, # this returns rlogtimes
+ 'dateformat' => 'S2', # S2 format time format is easier
+ 'entry_objects' => \@objs,
+ 'load_props' => 1,
+ 'load_text' => 1,
+ });
+ }
- $opts->{'contenttype'} = 'text/xml; charset='.$opts->{'saycharset'};
+ $opts->{'contenttype'} = 'text/xml; charset=' . $opts->{'saycharset'};
- ### load the log properties
- my %logprops = ();
- my $logtext;
- my $logdb = LJ::get_cluster_reader($u);
- LJ::load_log_props2($logdb, $u->{'userid'}, \@itemids, \%logprops);
- $logtext = LJ::get_logtext2($u, @itemids);
-
# set last-modified header, then let apache figure out
# whether we actually need to send the feed.
my $lastmod = 0;
- foreach my $item (@items) {
+
+ for my $obj ( @objs ) {
# revtime of the item.
- my $revtime = $logprops{$item->{itemid}}->{revtime};
+ my $revtime = $obj->prop('revtime');
$lastmod = $revtime if $revtime > $lastmod;
- # if we don't have a revtime, use the logtime of the item.
unless ($revtime) {
- my $itime = $LJ::EndOfTime - $item->{rlogtime};
+ # use the logtime of the item.
+ my $itime = $LJ::EndOfTime - $obj->{rlogtime};
$lastmod = $itime if $itime > $lastmod;
}
}
+
LJ::Request->set_last_modified($lastmod) if $lastmod;
# use this $lastmod as the feed's last-modified time
@@ -184,31 +189,27 @@
# load tags now that we have no chance of jumping out early
my $logtags = LJ::Tags::get_logtags($u, \@itemids);
- my %posteru = (); # map posterids to u objects
- LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @items], [$u]);
-
my @cleanitems;
- my @entries; # LJ::Entry objects
ENTRY:
- foreach my $it (@items)
- {
- # load required data
- my $itemid = $it->{'itemid'};
- my $ditemid = $itemid*256 + $it->{'anum'};
- my $entry_obj = LJ::Entry->new($u, ditemid => $ditemid);
- $entry_obj->handle_prefetched_props($logprops{$itemid});
+ foreach my $entry_obj (@objs) {
+ my $ditemid = $entry_obj->{ditemid};
- next ENTRY if $posteru{$it->{'posterid'}} && $posteru{$it->{'posterid'}}->{'statusvis'} eq 'S';
+ next ENTRY if $entry_obj->poster->{'statusvis'} eq 'S';
next ENTRY if $entry_obj && $entry_obj->is_suspended_for($remote);
- if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) {
- LJ::item_toutf8($u, \$logtext->{$itemid}->[0],
- \$logtext->{$itemid}->[1], $logprops{$itemid});
+ if ( $LJ::UNICODE && $entry_obj->prop('unknown8bit') ) {
+ LJ::item_toutf8(
+ $u,
+ \$entry_obj->{'subject'},
+ \$entry_obj->{'event'},
+ $entry_obj->prop,
+ );
}
# see if we have a subject and clean it
- my $subject = $logtext->{$itemid}->[0];
+ my $subject = $entry_obj->{'subject'};
+
if ($subject) {
$subject =~ s/[\r\n]/ /g;
LJ::CleanHTML::clean_subject_all(\$subject);
@@ -218,12 +219,12 @@
my $readmore = "<b>(<a href=\"$journalinfo->{link}$ditemid.html\">Read more ...</a>)</b>";
# empty string so we don't waste time cleaning an entry that won't be used
- my $event = $u->{'opt_synlevel'} eq 'title' ? '' : $logtext->{$itemid}->[1];
+ my $event = $u->{'opt_synlevel'} eq 'title' ? '' : $entry_obj->event_raw;
# clean the event, if non-empty
my $ppid = 0;
+
if ($event) {
-
# users without 'full_rss' get their logtext bodies truncated
# do this now so that the html cleaner will hopefully fix html we break
unless (LJ::get_cap($u, 'full_rss')) {
@@ -232,11 +233,12 @@
}
LJ::CleanHTML::clean_event(\$event,
- { 'wordlength' => 0,
- 'preformatted' => $logprops{$itemid}->{'opt_preformatted'},
- 'journalid' => $u->userid,
- 'posterid' => $it->{'posterid'},
- 'entry_url' => $entry_obj->url,
+ {
+ 'wordlength' => 0,
+ 'preformatted' => $entry_obj->prop('opt_preformatted'),
+ 'journalid' => $u->userid,
+ 'posterid' => $entry_obj->{'posterid'},
+ 'entry_url' => $entry_obj->url,
}
);
@@ -245,12 +247,12 @@
if ($u->{'opt_synlevel'} eq 'summary') {
# assume the first paragraph is terminated by two <br> or a </p>
# valid XML tags should be handled, even though it makes an uglier regex
- if ($event =~ m!
+ if ($event =~ m!
(.*?) ## any text
(?=<) ## followed by "<" (zero-width positive look-ahead assertion)
- ## and then either </p> or 2 BRs,
+ ## and then either </p> or 2 BRs,
## where BR is one of: <br></br>, <br> or <br/>
- ( (?:<br\s*/?\>(?:</br\s*>)?\s*){2} | (?:</p\s*>) ) !six)
+ ( (?:<br\s*/?\>(?:</br\s*>)?\s*){2} | (?:</p\s*>) ) !six)
{
# everything before the matched tag + the tag itself
# + a link to read more
@@ -264,13 +266,14 @@
my $name = LJ::Poll->new($pollid)->name;
if ($name) {
LJ::Poll->clean_poll(\$name);
- } else {
+ }
+ else {
$name = "#$pollid";
}
$event =~ s!<lj-poll-$pollid>!<div><a href="$LJ::SITEROOT/poll/?id=$pollid">View Poll: $name</a></div>!g;
}
-
+
my %args = LJ::Request->args;
LJ::EmbedModule->expand_entry($u, \$event, expand_full => 1)
if %args && $args{'unfold_embed'};
@@ -280,45 +283,47 @@
}
my $mood;
- if ($logprops{$itemid}->{'current_mood'}) {
- $mood = $logprops{$itemid}->{'current_mood'};
- } elsif ($logprops{$itemid}->{'current_moodid'}) {
- $mood = LJ::mood_name($logprops{$itemid}->{'current_moodid'}+0);
+
+ if ( $entry_obj->prop('current_mood') ) {
+ $mood = $entry_obj->prop('current_mood');
}
+ elsif ( $entry_obj->prop('current_moodid') ) {
+ $mood = LJ::mood_name($entry_obj->prop('current_moodid') + 0);
+ }
- my $createtime = $LJ::EndOfTime - $it->{rlogtime};
- my $cleanitem = {
- itemid => $itemid,
+ my $alldateparts = $entry_obj->{'eventtime'};
+ $alldateparts =~ s/[-:]/ /g;
+
+ my $createtime = $LJ::EndOfTime - $entry_obj->{rlogtime};
+ push @cleanitems, {
+ itemid => $entry_obj->jitemid,
ditemid => $ditemid,
subject => $subject,
event => $event,
createtime => $createtime,
- eventtime => $it->{alldatepart}, # ugly: this is of a different format than the other two times.
- modtime => $logprops{$itemid}->{revtime} || $createtime,
+ eventtime => $alldateparts,
+ modtime => $entry_obj->prop('revtime') || $createtime,
comments => $entry_obj->comments_shown,
- music => $logprops{$itemid}->{'current_music'},
+ music => $entry_obj->prop('current_music'),
mood => $mood,
ppid => $ppid,
- tags => [ values %{$logtags->{$itemid} || {}} ],
- security => $it->{security},
- posterid => $it->{posterid},
- replycount => $logprops{$itemid}->{'replycount'},
+ tags => [ values %{$logtags->{$entry_obj->jitemid} || {}} ],
+ security => $entry_obj->security,
+ posterid => $entry_obj->poster->id,
+ replycount => $entry_obj->prop('replycount'),
+ posteruser => $entry_obj->poster->user,
};
- push @cleanitems, $cleanitem;
- push @entries, $entry_obj;
}
# fix up the build date to use entry-time
- $journalinfo->{'builddate'} = LJ::TimeUtil->time_to_http($LJ::EndOfTime - $items[0]->{'rlogtime'}),
+ $journalinfo->{'builddate'} = LJ::TimeUtil->time_to_http($LJ::EndOfTime - $objs[0]->{'rlogtime'}),
- return $viewfunc->{handler}->($journalinfo, $u, $opts, \@cleanitems, \@entries);
+ return $viewfunc->{handler}->($journalinfo, $u, $opts, \@cleanitems, \@objs);
}
# the creator for the RSS XML syndication view
-sub create_view_rss
-{
- my ($journalinfo, $u, $opts, $cleanitems) = @_;
-
+sub create_view_rss {
+ my ($journalinfo, $u, $opts, $cleanitems, $objs) = @_;
my $ret;
# For Yandex ( http://blogs.yandex.ru/faq.xml?id=542563 )
@@ -367,30 +372,25 @@
$ret .= " </image>\n\n";
}
- my %posteru = (); # map posterids to u objects
- LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @$cleanitems], [$u]);
-
# output individual item blocks
-
- foreach my $it (@$cleanitems)
- {
+ foreach my $it (@$cleanitems) {
+ my $entry = shift @$objs;
my $itemid = $it->{itemid};
my $ditemid = $it->{ditemid};
- my $poster = $posteru{$it->{posterid}};
$ret .= "<item>\n";
$ret .= " <guid isPermaLink='true'>$journalinfo->{link}$ditemid.html</guid>\n";
$ret .= " <pubDate>" . LJ::TimeUtil->time_to_http($it->{createtime}) . "</pubDate>\n";
$ret .= " <title>" . LJ::exml($it->{subject}) . "</title>\n" if $it->{subject};
$ret .= " <author>" . LJ::exml($journalinfo->{email}) . "</author>" if $journalinfo->{email};
- $ret .= " <link>$journalinfo->{link}$ditemid.html</link>\n";
+ $ret .= " <link>" . $entry->url . "</link>\n";
# omit the description tag if we're only syndicating titles
# note: the $event was also emptied earlier, in make_feed
unless ($u->{'opt_synlevel'} eq 'title') {
$ret .= " <description>" . LJ::exml($it->{event}) . "</description>\n";
}
if ($it->{comments}) {
- $ret .= " <comments>$journalinfo->{link}$ditemid.html</comments>\n";
+ $ret .= " <comments>" . $entry->url . "</comments>\n";
}
$ret .= " <category>$_</category>\n" foreach map { LJ::exml($_) } @{$it->{tags} || []};
# support 'podcasting' enclosures
@@ -401,9 +401,9 @@
$ret .= " <media:title type=\"plain\">" . LJ::exml($it->{music}) . "</media:title>\n" if $it->{music};
$ret .= " <lj:mood>" . LJ::exml($it->{mood}) . "</lj:mood>\n" if $it->{mood};
$ret .= " <lj:security>" . LJ::exml($it->{security}) . "</lj:security>\n" if $it->{security};
- unless (LJ::u_equals($u, $poster)) {
- $ret .= " <lj:poster>" . LJ::exml($poster->user) . "</lj:poster>\n";
- $ret .= " <lj:posterid>" . $poster->userid . "</lj:posterid>\n";
+ unless ($u->{'userid'} == $it->{'posterid'}) {
+ $ret .= " <lj:poster>" . LJ::exml($it->{'posteruser'}) . "</lj:poster>\n";
+ $ret .= " <lj:posterid>" . $it->{'posterid'} . "</lj:posterid>\n";
}
$ret .= " <lj:reply-count>$it->{replycount}</lj:reply-count>\n";
@@ -444,7 +444,7 @@
for (my $i = 0; $i <= $now->hour; $i++) {
$sum += $today_hits[$i];
}
-
+
if ($now->hour < 23) {
my @yesterday_hits;
foreach my $el (@$data_y) {
@@ -533,6 +533,7 @@
unless ($opts->{'single_entry'}) {
$feed = XML::Atom::Feed->new( Version => 1 );
$xml = $feed->{doc};
+
unless ($xml){
die "Error: XML-LibXML is required"; ## sudo yum install perl-XML-LibXML
}
@@ -596,9 +597,9 @@
}
my $posteru = LJ::load_userids( map { $_->{posterid} } @$cleanitems);
+
# output individual item blocks
- foreach my $it (@$cleanitems)
- {
+ foreach my $it ( @$cleanitems ) {
my $itemid = $it->{itemid};
my $ditemid = $it->{ditemid};
my $poster = $posteru->{$it->{posterid}};
@@ -945,15 +946,15 @@
my $view;
if ($viewchunk eq '') {
- $view = "recent";
+ $view = "recent";
}
elsif ($viewchunk eq '/friends') {
- $view = "friends";
+ $view = "friends";
}
else {
$view = undef;
}
-
+
if ($view eq 'recent') {
# Only people (not communities, etc) can be OpenID authenticated
if ($person && LJ::OpenID->server_enabled) {
@@ -1109,12 +1110,12 @@
$opts->{handler_return} = 404;
return 404;
}
-
+
unless ($u->get_cap('latest_comments_rss')) {
$opts->{handler_return} = 403;
return;
}
-
+
my $ret;
$ret .= "<?xml version='1.0' encoding='$opts->{'saycharset'}' ?>\n";
$ret .= LJ::run_hook("bot_director", "<!-- ", " -->") . "\n";
@@ -1154,7 +1155,7 @@
my $thread_url = $c->thread_url;
my $subject = $c->subject_raw;
LJ::CleanHTML::clean_subject_all(\$subject);
-
+
$ret .= "<item>\n";
$ret .= " <guid isPermaLink='true'>$thread_url</guid>\n";
$ret .= " <pubDate>" . LJ::TimeUtil->time_to_http($r->{datepostunix}) . "</pubDate>\n";
Modified: trunk/cgi-bin/ljlib.pl
===================================================================
--- trunk/cgi-bin/ljlib.pl 2011-07-12 06:24:19 UTC (rev 19464)
+++ trunk/cgi-bin/ljlib.pl 2011-07-12 06:57:34 UTC (rev 19465)
@@ -612,20 +612,21 @@
# - showtypes: /[PICNY]/
# returns: Array of item hashrefs containing the same elements
# </LJFUNC>
-sub get_friend_items
-{
+sub get_friend_items {
&nodb;
my $opts = shift;
my $dbr = LJ::get_db_reader();
my $sth;
- my $userid = $opts->{'userid'}+0;
+ my $userid = $opts->{'userid'} + 0;
+ $userid = $opts->{'u'}->{'userid'} unless $userid;
return () if $LJ::FORCE_EMPTY_FRIENDS{$userid};
# 'remote' opt takes precendence, then 'remoteid'
my $remote = $opts->{'remote'};
my $remoteid = $remote ? $remote->{'userid'} : 0;
+
if ($remoteid == 0 && $opts->{'remoteid'}) {
$remoteid = $opts->{'remoteid'} + 0;
$remote = LJ::load_userid($remoteid);
@@ -642,13 +643,13 @@
}
my @items = ();
- my $itemshow = $opts->{'itemshow'}+0;
- my $skip = $opts->{'skip'}+0;
+ my $itemshow = $opts->{'itemshow'} + 0;
+ my $skip = $opts->{'skip'} + 0;
my $getitems = $itemshow + $skip;
# friendspage per day is allowed only for journals with
# special cap 'friendspage_per_day'
- my $events_date = $opts->{u}->get_cap('friendspage_per_day')
+ my $events_date = $opts->{'u'}->get_cap('friendspage_per_day')
? $opts->{events_date}
: '';
@@ -708,7 +709,7 @@
if ($LJ::SLOPPY_FRIENDS_THRESHOLD && $fcount > $LJ::SLOPPY_FRIENDS_THRESHOLD) {
$tu_opts->{memcache_only} = 1;
}
-
+
my $times = $events_date
? LJ::get_times_multi($tu_opts, keys %$friends)
: {updated => LJ::get_timeupdate_multi($tu_opts, keys %$friends)};
@@ -722,11 +723,11 @@
push @friends_buffer, [ $fid, $rupdate, $clusterid, $friends->{$fid}, $fu ];
}
- @friends_buffer =
- sort { $a->[1] <=> $b->[1] }
- grep {
+ @friends_buffer =
+ sort { $a->[1] <=> $b->[1] }
+ grep {
$timeupdate->{$_->[0]} >= $lastmax and # reverse index
- ($events_date
+ ($events_date
? $times->{created}->{$_->[0]} < $events_date
: 1
)
@@ -978,11 +979,51 @@
# remove skipped ones
splice(@items, 0, $skip) if $skip;
+ my ( @itemids, %owner_itemsids );
+
# get items
foreach (@items) {
$opts->{'owners'}->{$_->{'ownerid'}} = 1;
+
+ # construct an LJ::Entry singleton
+ my $entry = LJ::Entry->new(
+ $_->{'journalid'},
+ 'jitemid' => $_->{'itemid'},
+ 'anum' => $_->{'anum'},
+ 'rlogtime' => $_->{'rlogtime'},
+ );
+ $entry->absorb_row($_);
+ push @{$opts->{'entry_objects'}}, $entry;
+ push @{$opts->{'itemids'}}, $_->{'itemid'};
+ push @{$owner_itemsids{ $_->{'journalid'} }->{id}}, $_->{'itemid'};
+ push @{$owner_itemsids{ $_->{'journalid'} }->{entry}}, \$opts->{'entry_objects'}->[-1];
}
+ if ( exists $opts->{load_props} && $opts->{load_props} ) {
+ my %logprops = ();
+
+ for my $journal ( keys %owner_itemsids ) {
+ LJ::load_log_props2($journal, $owner_itemsids{ $journal }->{id}, \%logprops);
+ }
+
+ for my $entry ( @{$opts->{'entry_objects'}} ) {
+ $entry->handle_prefetched_props($logprops{$entry->{jitemid}});
+ }
+ }
+
+ if ( exists $opts->{load_text} && $opts->{load_text} ) {
+ my $texts;
+
+ for my $journal ( keys %owner_itemsids ) {
+ $texts = LJ::get_logtext2(LJ::load_userid($journal), @{$owner_itemsids{ $journal }->{id}} );
+
+ for my $rentry ( @{$owner_itemsids{ $journal }->{entry}} ) {
+ $$rentry->handle_prefetched_text( $texts->{ $$rentry->{jitemid} }->[0], $texts->{ $$rentry->{jitemid} }->[1] );
+ }
+ }
+ }
+
+
# return the itemids grouped by clusters, if callers wants it.
if (ref $opts->{'idsbycluster'} eq "HASH") {
foreach (@items) {
@@ -1044,7 +1085,7 @@
my $err = $opts->{'err'};
my $userid = $opts->{'userid'}+0;
- my $u = LJ::load_userid($userid)
+ my $u = LJ::load_userid($userid)
or die "No such userid: $userid";
# 'remote' opt takes precendence, then 'remoteid'
@@ -1058,13 +1099,16 @@
my $max_hints = $LJ::MAX_SCROLLBACK_LASTN; # temporary
my $sort_key = "revttime";
- my $clusterid = $u->{'clusterid'}+0;
+ my $clusterid = $u->{'clusterid'} + 0;
my @sources = ("cluster$clusterid");
+
if (my $ab = $LJ::CLUSTER_PAIR_ACTIVE{$clusterid}) {
@sources = ("cluster${clusterid}${ab}");
}
+
unshift @sources, ("cluster${clusterid}lite", "cluster${clusterid}slave")
if $opts->{'clustersource'} eq "slave";
+
my $logdb = LJ::get_dbh(@sources);
# community/friend views need to post by log time, not event time
@@ -1161,7 +1205,7 @@
# set $jitemidwhere iff we have jitemids
if (@$jitemids) {
$jitemidwhere = " AND jitemid IN (" .
- join(',', map { $_+0 } @$jitemids) .
+ join(',', map { $_ + 0 } @$jitemids) .
")";
} else {
# no items, so show no entries
@@ -1260,6 +1304,7 @@
# keep track of the last alldatepart, and a per-minute buffer
my $last_time;
my @buf;
+
my $flush = sub {
return unless @buf;
push @items, sort { $b->{itemid} <=> $a->{itemid} } @buf;
@@ -1274,7 +1319,7 @@
$last_time = $li->{alldatepart};
# construct an LJ::Entry singleton
- my $entry = LJ::Entry->new($userid, jitemid => $li->{itemid});
+ my $entry = LJ::Entry->new($userid, jitemid => $li->{itemid}, rlogtime => $li->{rlogtime});
$entry->absorb_row($li);
push @{$opts->{'entry_objects'}}, $entry;
}
