Типа я (zilogic) wrote in changelog,
Типа я
zilogic
changelog

[livejournal] r19465: LJSUP-9270: Creare RSS feed for friends ...

Committer: amyshkin
LJSUP-9270: Creare RSS feed for friends page
U   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;
     }

Tags: dat, livejournal, pl, pm, zilogic
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments