fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-09-08 06:48 am

[dw-free] cleaning up userpics code

[commit: http://hg.dwscoalition.org/dw-free/rev/e84aad104e41]

http://bugs.dwscoalition.org/show_bug.cgi?id=513

More functions under LJ::Userpic and on the user, rather than in package LJ

Patch by [personal profile] kareila.

Files modified:
  • cgi-bin/LJ/User.pm
  • cgi-bin/ljfeed.pl
  • cgi-bin/ljprotocol.pl
  • cgi-bin/ljuserpics.pl
  • htdocs/preview/entry.bml
--------------------------------------------------------------------------------
diff -r b29d6cfc5a83 -r e84aad104e41 cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm	Wed Sep 08 14:41:32 2010 +0800
+++ b/cgi-bin/LJ/User.pm	Wed Sep 08 14:47:35 2010 +0800
@@ -6234,15 +6234,228 @@ sub get_userpic_count {
     return $count;
 }
 
+# des: Given a user, gets their userpic information.
+# des-opts: Optional; hash of options, 'load_comments', 'load_urls', 'load_descriptions'.
+# returns: hash of userpicture information;
+#          for efficiency, we store the userpic structures
+#          in memcache in a packed format.
+# info: memory format:
+#       [
+#       version number of format,
+#       userid,
+#       "packed string", which expands to an array of {width=>..., ...}
+#       "packed string", which expands to { 'kw1' => id, 'kw2' => id, ...}
+#       ]
+
+sub get_userpic_info {
+    my ( $u, $opts ) = @_;
+    return undef unless LJ::isu( $u ) && $u->clusterid;
+
+    # in the cache, cool, well unless it doesn't have comments or urls or descriptions
+    # and we need them
+    if (my $cachedata = $LJ::CACHE_USERPIC_INFO{ $u->userid }) {
+        my $good = 1;
+        $good = 0 if $opts->{load_comments} && ! $cachedata->{_has_comments};
+        $good = 0 if $opts->{load_urls} && ! $cachedata->{_has_urls};
+        $good = 0 if $opts->{load_descriptions} && ! $cachedata->{_has_descriptions};
+
+        return $cachedata if $good;
+    }
+
+    my $VERSION_PICINFO = 3;
+
+    my $memkey = [$u->userid,"upicinf:$u->{'userid'}"];
+    my ($info, $minfo);
+
+    if ($minfo = LJ::MemCache::get($memkey)) {
+        # the pre-versioned memcache data was a two-element hash.
+        # since then, we use an array and include a version number.
+
+        if (ref $minfo eq 'HASH' ||
+            $minfo->[0] != $VERSION_PICINFO) {
+            # old data in the cache.  delete.
+            LJ::MemCache::delete($memkey);
+        } else {
+            my (undef, $picstr, $kwstr) = @$minfo;
+            $info = {
+                'pic' => {},
+                'kw' => {},
+            };
+            while (length $picstr >= 7) {
+                my $pic = { userid => $u->{'userid'} };
+                ($pic->{picid},
+                 $pic->{width}, $pic->{height},
+                 $pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, '');
+                $info->{pic}->{$pic->{picid}} = $pic;
+            }
+
+            my ($pos, $nulpos);
+            $pos = $nulpos = 0;
+            while (($nulpos = index($kwstr, "\0", $pos)) > 0) {
+                my $kw = substr($kwstr, $pos, $nulpos-$pos);
+                my $id = unpack("N", substr($kwstr, $nulpos+1, 4));
+                $pos = $nulpos + 5; # skip NUL + 4 bytes.
+                $info->{kw}->{$kw} = $info->{pic}->{$id} if $info;
+            }
+        }
+
+        # Load picture comments
+        if ( $opts->{load_comments} ) {
+            my $commemkey = [$u->userid, "upiccom:" . $u->userid];
+            my $comminfo = LJ::MemCache::get( $commemkey );
+
+            if ( defined( $comminfo ) ) {
+                my ( $pos, $nulpos );
+                $pos = $nulpos = 0;
+                while ( ($nulpos = index( $comminfo, "\0", $pos )) > 0 ) {
+                    my $comment = substr( $comminfo, $pos, $nulpos-$pos );
+                    my $id = unpack( "N", substr( $comminfo, $nulpos+1, 4 ) );
+                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
+                    $info->{pic}->{$id}->{comment} = $comment;
+                    $info->{comment}->{$id} = $comment;
+                }
+                $info->{_has_comments} = 1;
+            } else { # Requested to load comments, but they aren't in memcache
+                     # so force a db load
+                undef $info;
+            }
+        }
+
+        # Load picture urls
+        if ( $opts->{load_urls} && $info ) {
+            my $urlmemkey = [$u->userid, "upicurl:" . $u->userid];
+            my $urlinfo = LJ::MemCache::get( $urlmemkey );
+
+            if ( defined( $urlinfo ) ) {
+                my ( $pos, $nulpos );
+                $pos = $nulpos = 0;
+                while ( ($nulpos = index( $urlinfo, "\0", $pos )) > 0 ) {
+                    my $url = substr( $urlinfo, $pos, $nulpos-$pos );
+                    my $id = unpack( "N", substr( $urlinfo, $nulpos+1, 4 ) );
+                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
+                    $info->{pic}->{$id}->{url} = $url;
+                }
+                $info->{_has_urls} = 1;
+            } else { # Requested to load urls, but they aren't in memcache
+                     # so force a db load
+                undef $info;
+            }
+        }
+
+        # Load picture descriptions
+        if ( $opts->{load_descriptions} && $info ) {
+            my $descmemkey = [$u->userid, "upicdes:" . $u->userid];
+            my $descinfo = LJ::MemCache::get( $descmemkey );
+
+            if ( defined ( $descinfo ) ) {
+                my ( $pos, $nulpos );
+                $pos = $nulpos = 0;
+                while ( ($nulpos = index( $descinfo, "\0", $pos )) > 0 ) {
+                    my $description = substr( $descinfo, $pos, $nulpos-$pos );
+                    my $id = unpack( "N", substr( $descinfo, $nulpos+1, 4 ) );
+                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
+                    $info->{pic}->{$id}->{description} = $description;
+                    $info->{description}->{$id} = $description;
+                }
+                $info->{_has_descriptions} = 1;
+            } else { # Requested to load descriptions, but they aren't in memcache
+                     # so force a db load
+                undef $info;
+            }
+        }
+    }
+
+    my %minfocom; # need this in this scope
+    my %minfourl;
+    my %minfodesc;
+    unless ($info) {
+        $info = {
+            'pic' => {},
+            'kw' => {},
+        };
+        my ($picstr, $kwstr);
+        my $sth;
+        my $dbcr = LJ::get_cluster_def_reader($u);
+        my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader();
+        return undef unless $dbcr && $db;
+
+        $sth = $dbcr->prepare( "SELECT picid, width, height, state, userid, comment, url, description ".
+                               "FROM userpic2 WHERE userid=?" );
+        $sth->execute( $u->userid );
+        my @pics;
+        while (my $pic = $sth->fetchrow_hashref) {
+            next if $pic->{state} eq 'X'; # no expunged pics in list
+            push @pics, $pic;
+            $info->{'pic'}->{$pic->{'picid'}} = $pic;
+            $minfocom{int($pic->{picid})} = $pic->{comment}
+                if $opts->{load_comments} && $pic->{comment};
+            $minfourl{int($pic->{picid})} = $pic->{url}
+                if $opts->{load_urls} && $pic->{url};
+            $minfodesc{int($pic->{picid})} = $pic->{description}
+                if $opts->{load_descriptions} && $pic->{description}; 
+        }
+
+
+        $picstr = join('', map { pack("NCCA", $_->{picid},
+                                 $_->{width}, $_->{height}, $_->{state}) } @pics);
+
+        $sth = $dbcr->prepare( "SELECT k.keyword, m.picid FROM userpicmap2 m, userkeywords k ".
+                               "WHERE k.userid=? AND m.kwid=k.kwid AND m.userid=k.userid" );
+        $sth->execute($u->{'userid'});
+        my %minfokw;
+        while (my ($kw, $id) = $sth->fetchrow_array) {
+            next unless $info->{'pic'}->{$id};
+            next if $kw =~ /[\n\r\0]/;  # used to be a bug that allowed these to get in.
+            $info->{'kw'}->{$kw} = $info->{'pic'}->{$id};
+            $minfokw{$kw} = int($id);
+        }
+        $kwstr = join('', map { pack("Z*N", $_, $minfokw{$_}) } keys %minfokw);
+
+        $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
+        $minfo = [ $VERSION_PICINFO, $picstr, $kwstr ];
+        LJ::MemCache::set($memkey, $minfo);
+
+        if ( $opts->{load_comments} ) {
+            $info->{comment} = \%minfocom;
+            my $commentstr = join( '', map { pack( "Z*N", $minfocom{$_}, $_ ) } keys %minfocom );
+
+            my $memkey = [$u->userid, "upiccom:" . $u->userid];
+            LJ::MemCache::set( $memkey, $commentstr );
+
+            $info->{_has_comments} = 1;
+        }
+
+        if ($opts->{load_urls}) {
+            my $urlstr = join( '', map { pack( "Z*N", $minfourl{$_}, $_ ) } keys %minfourl );
+
+            my $memkey = [$u->userid, "upicurl:" . $u->userid];
+            LJ::MemCache::set( $memkey, $urlstr );
+
+            $info->{_has_urls} = 1;
+        }
+
+        if ($opts->{load_descriptions}) {
+            $info->{description} = \%minfodesc;
+            my $descstring = join( '', map { pack( "Z*N", $minfodesc{$_}, $_ ) } keys %minfodesc );
+
+            my $memkey = [$u->userid, "upicdes:" . $u->userid];
+            LJ::MemCache::set( $memkey, $descstring );
+
+            $info->{_has_descriptions} = 1;
+        }
+    }
+
+    $LJ::CACHE_USERPIC_INFO{$u->userid} = $info;
+    return $info;
+}
+
 # gets a mapping from userpic ids to keywords for this User.
 sub get_userpic_kw_map {
-    my $self = shift;
-
-    if ( $self->{picid_kw_map} ) {
-        return $self->{picid_kw_map};
-    }
-
-    my $picinfo = LJ::get_userpic_info( $self->userid, {load_comments => 0} );
+    my ( $u ) = @_;
+
+    return $u->{picid_kw_map} if $u->{picid_kw_map};  # cache
+
+    my $picinfo = $u->get_userpic_info( { load_comments => 0 } );
     my $keywords = {};
     foreach my $keyword ( keys %{$picinfo->{kw}} ) {
         my $picid = $picinfo->{kw}->{$keyword}->{picid};
@@ -6250,8 +6463,7 @@ sub get_userpic_kw_map {
         push @{$keywords->{$picid}}, $keyword if ( $keyword && $picid );
     }
 
-    $self->{picid_kw_map} = $keywords;
-    return $keywords;
+    return $u->{picid_kw_map} = $keywords;
 }
 
 # <LJFUNC>
diff -r b29d6cfc5a83 -r e84aad104e41 cgi-bin/ljfeed.pl
--- a/cgi-bin/ljfeed.pl	Wed Sep 08 14:41:32 2010 +0800
+++ b/cgi-bin/ljfeed.pl	Wed Sep 08 14:47:35 2010 +0800
@@ -901,7 +901,7 @@ sub create_view_userpics {
 
     # now start building all the userpic data
     # start up by loading all of our userpic information and creating that part of the feed
-    my $info = LJ::get_userpic_info( $u, { load_comments => 1, load_urls => 1, load_descriptions => 1 } );
+    my $info = $u->get_userpic_info( { load_comments => 1, load_urls => 1, load_descriptions => 1 } );
 
     my %keywords = ();
     while (my ($kw, $pic) = each %{$info->{kw}}) {
diff -r b29d6cfc5a83 -r e84aad104e41 cgi-bin/ljprotocol.pl
--- a/cgi-bin/ljprotocol.pl	Wed Sep 08 14:41:32 2010 +0800
+++ b/cgi-bin/ljprotocol.pl	Wed Sep 08 14:47:35 2010 +0800
@@ -3058,9 +3058,10 @@ sub hash_menus
 
 sub list_pickws
 {
-    my $u = shift;
-
-    my $pi = LJ::get_userpic_info($u);
+    my ( $u ) = @_;
+    return [] unless LJ::isu( $u );
+
+    my $pi = $u->get_userpic_info;
     my @res;
 
     my %seen;  # mashifiedptr -> 1
diff -r b29d6cfc5a83 -r e84aad104e41 cgi-bin/ljuserpics.pl
--- a/cgi-bin/ljuserpics.pl	Wed Sep 08 14:41:32 2010 +0800
+++ b/cgi-bin/ljuserpics.pl	Wed Sep 08 14:47:35 2010 +0800
@@ -108,242 +108,18 @@ sub load_userpics {
     }
 }
 
-# <LJFUNC>
-# name: LJ::get_userpic_info
-# des: Given a user, gets their userpic information.
-# args: uuid, opts?
-# des-uuid: userid, or user object.
-# des-opts: Optional; hash of options, 'load_comments', 'load_urls', 'load_descriptions'.
-# returns: hash of userpicture information;
-#          for efficiency, we store the userpic structures
-#          in memcache in a packed format.
-# info: memory format:
-#       [
-#       version number of format,
-#       userid,
-#       "packed string", which expands to an array of {width=>..., ...}
-#       "packed string", which expands to { 'kw1' => id, 'kw2' => id, ...}
-#       ]
-# </LJFUNC>
-
-sub get_userpic_info
-{
-    my ($uuid, $opts) = @_;
-    return undef unless $uuid;
-    my $userid = LJ::want_userid($uuid);
-    my $u = LJ::want_user($uuid); # This should almost always be in memory already
-    return undef unless $u && $u->{clusterid};
-
-    # in the cache, cool, well unless it doesn't have comments or urls or descriptions
-    # and we need them
-    if (my $cachedata = $LJ::CACHE_USERPIC_INFO{$userid}) {
-        my $good = 1;
-        $good = 0 if $opts->{load_comments} && ! $cachedata->{_has_comments};
-        $good = 0 if $opts->{load_urls} && ! $cachedata->{_has_urls};
-        $good = 0 if $opts->{load_descriptions} && ! $cachedata->{_has_descriptions};
-
-        return $cachedata if $good;
-    }
-
-    my $VERSION_PICINFO = 3;
-
-    my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
-    my ($info, $minfo);
-
-    if ($minfo = LJ::MemCache::get($memkey)) {
-        # the pre-versioned memcache data was a two-element hash.
-        # since then, we use an array and include a version number.
-
-        if (ref $minfo eq 'HASH' ||
-            $minfo->[0] != $VERSION_PICINFO) {
-            # old data in the cache.  delete.
-            LJ::MemCache::delete($memkey);
-        } else {
-            my (undef, $picstr, $kwstr) = @$minfo;
-            $info = {
-                'pic' => {},
-                'kw' => {},
-            };
-            while (length $picstr >= 7) {
-                my $pic = { userid => $u->{'userid'} };
-                ($pic->{picid},
-                 $pic->{width}, $pic->{height},
-                 $pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, '');
-                $info->{pic}->{$pic->{picid}} = $pic;
-            }
-
-            my ($pos, $nulpos);
-            $pos = $nulpos = 0;
-            while (($nulpos = index($kwstr, "\0", $pos)) > 0) {
-                my $kw = substr($kwstr, $pos, $nulpos-$pos);
-                my $id = unpack("N", substr($kwstr, $nulpos+1, 4));
-                $pos = $nulpos + 5; # skip NUL + 4 bytes.
-                $info->{kw}->{$kw} = $info->{pic}->{$id} if $info;
-            }
-        }
-
-        # Load picture comments
-        if ( $opts->{load_comments} ) {
-            my $commemkey = [$u->userid, "upiccom:" . $u->userid];
-            my $comminfo = LJ::MemCache::get( $commemkey );
-
-            if ( defined( $comminfo ) ) {
-                my ( $pos, $nulpos );
-                $pos = $nulpos = 0;
-                while ( ($nulpos = index( $comminfo, "\0", $pos )) > 0 ) {
-                    my $comment = substr( $comminfo, $pos, $nulpos-$pos );
-                    my $id = unpack( "N", substr( $comminfo, $nulpos+1, 4 ) );
-                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
-                    $info->{pic}->{$id}->{comment} = $comment;
-                    $info->{comment}->{$id} = $comment;
-                }
-                $info->{_has_comments} = 1;
-            } else { # Requested to load comments, but they aren't in memcache
-                     # so force a db load
-                undef $info;
-            }
-        }
-
-        # Load picture urls
-        if ( $opts->{load_urls} && $info ) {
-            my $urlmemkey = [$u->userid, "upicurl:" . $u->userid];
-            my $urlinfo = LJ::MemCache::get( $urlmemkey );
-
-            if ( defined( $urlinfo ) ) {
-                my ( $pos, $nulpos );
-                $pos = $nulpos = 0;
-                while ( ($nulpos = index( $urlinfo, "\0", $pos )) > 0 ) {
-                    my $url = substr( $urlinfo, $pos, $nulpos-$pos );
-                    my $id = unpack( "N", substr( $urlinfo, $nulpos+1, 4 ) );
-                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
-                    $info->{pic}->{$id}->{url} = $url;
-                }
-                $info->{_has_urls} = 1;
-            } else { # Requested to load urls, but they aren't in memcache
-                     # so force a db load
-                undef $info;
-            }
-        }
-
-        # Load picture descriptions
-        if ( $opts->{load_descriptions} && $info ) {
-            my $descmemkey = [$u->userid, "upicdes:" . $u->userid];
-            my $descinfo = LJ::MemCache::get( $descmemkey );
-
-            if ( defined ( $descinfo ) ) {
-                my ( $pos, $nulpos );
-                $pos = $nulpos = 0;
-                while ( ($nulpos = index( $descinfo, "\0", $pos )) > 0 ) {
-                    my $description = substr( $descinfo, $pos, $nulpos-$pos );
-                    my $id = unpack( "N", substr( $descinfo, $nulpos+1, 4 ) );
-                    $pos = $nulpos + 5; # skip NUL + 4 bytes.
-                    $info->{pic}->{$id}->{description} = $description;
-                    $info->{description}->{$id} = $description;
-                }
-                $info->{_has_descriptions} = 1;
-            } else { # Requested to load descriptions, but they aren't in memcache
-                     # so force a db load
-                undef $info;
-            }
-        }
-    }
-
-    my %minfocom; # need this in this scope
-    my %minfourl;
-    my %minfodesc;
-    unless ($info) {
-        $info = {
-            'pic' => {},
-            'kw' => {},
-        };
-        my ($picstr, $kwstr);
-        my $sth;
-        my $dbcr = LJ::get_cluster_def_reader($u);
-        my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader();
-        return undef unless $dbcr && $db;
-
-        $sth = $dbcr->prepare( "SELECT picid, width, height, state, userid, comment, url, description ".
-                               "FROM userpic2 WHERE userid=?" );
-        $sth->execute( $u->userid );
-        my @pics;
-        while (my $pic = $sth->fetchrow_hashref) {
-            next if $pic->{state} eq 'X'; # no expunged pics in list
-            push @pics, $pic;
-            $info->{'pic'}->{$pic->{'picid'}} = $pic;
-            $minfocom{int($pic->{picid})} = $pic->{comment}
-                if $opts->{load_comments} && $pic->{comment};
-            $minfourl{int($pic->{picid})} = $pic->{url}
-                if $opts->{load_urls} && $pic->{url};
-            $minfodesc{int($pic->{picid})} = $pic->{description}
-                if $opts->{load_descriptions} && $pic->{description}; 
-        }
-
-
-        $picstr = join('', map { pack("NCCA", $_->{picid},
-                                 $_->{width}, $_->{height}, $_->{state}) } @pics);
-
-        $sth = $dbcr->prepare( "SELECT k.keyword, m.picid FROM userpicmap2 m, userkeywords k ".
-                               "WHERE k.userid=? AND m.kwid=k.kwid AND m.userid=k.userid" );
-        $sth->execute($u->{'userid'});
-        my %minfokw;
-        while (my ($kw, $id) = $sth->fetchrow_array) {
-            next unless $info->{'pic'}->{$id};
-            next if $kw =~ /[\n\r\0]/;  # used to be a bug that allowed these to get in.
-            $info->{'kw'}->{$kw} = $info->{'pic'}->{$id};
-            $minfokw{$kw} = int($id);
-        }
-        $kwstr = join('', map { pack("Z*N", $_, $minfokw{$_}) } keys %minfokw);
-
-        $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
-        $minfo = [ $VERSION_PICINFO, $picstr, $kwstr ];
-        LJ::MemCache::set($memkey, $minfo);
-
-        if ( $opts->{load_comments} ) {
-            $info->{comment} = \%minfocom;
-            my $commentstr = join( '', map { pack( "Z*N", $minfocom{$_}, $_ ) } keys %minfocom );
-
-            my $memkey = [$u->userid, "upiccom:" . $u->userid];
-            LJ::MemCache::set( $memkey, $commentstr );
-
-            $info->{_has_comments} = 1;
-        }
-
-        if ($opts->{load_urls}) {
-            my $urlstr = join( '', map { pack( "Z*N", $minfourl{$_}, $_ ) } keys %minfourl );
-
-            my $memkey = [$u->userid, "upicurl:" . $u->userid];
-            LJ::MemCache::set( $memkey, $urlstr );
-
-            $info->{_has_urls} = 1;
-        }
-
-        if ($opts->{load_descriptions}) {
-            $info->{description} = \%minfodesc;
-            my $descstring = join( '', map { pack( "Z*N", $minfodesc{$_}, $_ ) } keys %minfodesc );
-
-            my $memkey = [$u->userid, "upicdes:" . $u->userid];
-            LJ::MemCache::set( $memkey, $descstring );
-
-            $info->{_has_descriptions} = 1;
-        }
-    }
-
-    $LJ::CACHE_USERPIC_INFO{$u->userid} = $info;
-    return $info;
-}
-
 sub get_picid_from_keyword
 {
     my ($u, $kw, $default) = @_;
     $default ||= (ref $u ? $u->{'defaultpicid'} : 0);
     return $default unless $kw;
 
-    my $info = LJ::get_userpic_info($u);
+    my $info = LJ::isu( $u ) ? $u->get_userpic_info : undef;
     return $default unless $info;
 
     my $pr = $info->{'kw'}{$kw};
     # normal keyword
-    return $pr->{picid} if $pr->{'picid'};
+    return $pr->{picid} if $pr->{picid};
 
     # the lame "pic#2343" thing when they didn't assign a keyword
     if ($kw =~ /^pic\#(\d+)$/) {
diff -r b29d6cfc5a83 -r e84aad104e41 htdocs/preview/entry.bml
--- a/htdocs/preview/entry.bml	Wed Sep 08 14:41:32 2010 +0800
+++ b/htdocs/preview/entry.bml	Wed Sep 08 14:47:35 2010 +0800
@@ -121,14 +121,10 @@ _c?>
 
         if ($u) {
             $ret .= "<table><tr valign='middle'>";
-            my $picid = LJ::get_picid_from_keyword($up, $req{'prop_picture_keyword'});
-            my $upics = LJ::get_userpic_info($up);
-            my $pic   = $upics->{'pic'}->{$picid};
 
-            if ($pic) {
-                my $userpic = LJ::Userpic->new( $up, $picid );
-                $ret .= "<td>" . $userpic->imgtag . "</td>";   
-            }
+            my $pic = LJ::Userpic->new_from_keyword( $up, $req{prop_picture_keyword} );
+            my $imgtag = $pic ? $pic->imgtag : undef;
+            $ret .= "<td>$imgtag</td>" if $imgtag;
 
             $ret .= "<td>";
             if ( $u->is_community ) {
--------------------------------------------------------------------------------