[dw-free] Need new trust group method
[commit: http://hg.dwscoalition.org/dw-free/rev/eae6da291a54]
http://bugs.dwscoalition.org/show_bug.cgi?id=442
Add trust_list and trust_group_list methods to LJ::User.
Patch by
mark.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=442
Add trust_list and trust_group_list methods to LJ::User.
Patch by
![[staff profile]](https://www.dreamwidth.org/img/silk/identity/user_staff.png)
Files modified:
- bin/test/test-wtf
- cgi-bin/DW/User/Edges/WatchTrust.pm
- cgi-bin/DW/User/Edges/WatchTrust/Loader.pm
-------------------------------------------------------------------------------- diff -r 8149c4258dbf -r eae6da291a54 bin/test/test-wtf --- a/bin/test/test-wtf Fri Mar 06 07:33:37 2009 +0000 +++ b/bin/test/test-wtf Fri Mar 06 07:52:58 2009 +0000 @@ -27,7 +27,7 @@ sub rst { foreach ( $u1->id, $u2->id ); foreach my $u ( $u1, $u2 ) { - foreach my $mc ( qw/ trust_group / ) { + foreach my $mc ( qw/ trust_group wt_list / ) { LJ::memcache_kill( $u, $mc ); } } @@ -80,6 +80,13 @@ push @tests, [ 'trust list one member', } ]; ################################################################################ +push @tests, [ 'trust_list one member', sub +{ + my $ids = $u1->trust_list; + return scalar( keys %$ids ) == 1 ? 1 : 0; +} ]; + +################################################################################ push @tests, [ 'mutually trust list empty', sub { my @ids = $u1->mutually_trusted_userids; @@ -123,6 +130,13 @@ push @tests, [ 'trust list empty', sub { my @ids = $u1->trusted_userids; return scalar( @ids ) == 0 ? 1 : 0; +} ]; + +################################################################################ +push @tests, [ 'trust_list empty', sub +{ + my $ids = $u1->trust_list; + return scalar( keys %$ids ) == 0 ? 1 : 0; } ]; ################################################################################ @@ -346,8 +360,19 @@ push @tests, [ 'validate trustmask == 1' push @tests, [ 'validate trustmask == 1', sub { rst(); + + # have to create a group with a known id for these tests + $u1->edit_trust_group( id => 1, groupname => 'bar group', _force_create => 1 ); + $u1->add_edge( $u2, trust => { nonotify => 1 } ); return ( $u1->trustmask( $u2 ) == 1 ) ? 1 : 0; +} ]; + +################################################################################ +push @tests, [ 'validate nobody in group 1', sub +{ + my $ids = $u1->trust_group_list( id => 1 ); + return ( scalar ( keys %$ids ) == 0 ) ? 1 : 0; } ]; ################################################################################ @@ -355,6 +380,13 @@ push @tests, [ 'add to group, validate t { $u1->edit_trustmask( $u2, add => 1 ); return ( $u1->trustmask( $u2 ) == 3 ) ? 1 : 0; +} ]; + +################################################################################ +push @tests, [ 'validate in group 1', sub +{ + my $ids = $u1->trust_group_list( id => 1 ); + return ( scalar ( keys %$ids ) == 1 ) ? 1 : 0; } ]; ################################################################################ diff -r 8149c4258dbf -r eae6da291a54 cgi-bin/DW/User/Edges/WatchTrust.pm --- a/cgi-bin/DW/User/Edges/WatchTrust.pm Fri Mar 06 07:33:37 2009 +0000 +++ b/cgi-bin/DW/User/Edges/WatchTrust.pm Fri Mar 06 07:52:58 2009 +0000 @@ -126,7 +126,7 @@ sub _add_wt_edge { LJ::MemCache::delete( [$from_userid, "trustmask:$from_userid:$to_userid"] ); LJ::memcache_kill( $to_userid, 'wt_edges_rev' ); LJ::memcache_kill( $from_userid, 'wt_edges' ); - LJ::memcache_kill( $from_userid, 'watch_list' ); + LJ::memcache_kill( $from_userid, 'wt_list' ); LJ::memcache_kill( $from_userid, 'watched' ); LJ::memcache_kill( $from_userid, 'trusted' ); LJ::memcache_kill( $to_userid, 'watched_by' ); @@ -204,7 +204,7 @@ sub _del_wt_edge { # kill memcaches LJ::memcache_kill( $from_u, 'wt_edges' ); LJ::memcache_kill( $to_u, 'wt_edges_rev' ); - LJ::memcache_kill( $from_u, 'watch_list' ); + LJ::memcache_kill( $from_u, 'wt_list' ); LJ::memcache_kill( $from_u, 'watched' ); LJ::memcache_kill( $from_u, 'trusted' ); LJ::memcache_kill( $to_u, 'watched_by' ); @@ -525,6 +525,100 @@ sub mutually_trusted_userids { # { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN } # } # +# one entry in the hashref for everything the given user trusts. note that fgcolor/bgcolor +# are only really useful for watched users, so these will be default/empty if the user +# is only trusted. +# +# arguments is a hash of options +# memcache_only => 1, if set, never hit database +# force_database => 1, if set, ALWAYS hit database (DANGER) +# +sub trust_list { + my ( $u, %args ) = @_; + $u = LJ::want_user( $u ) or confess 'invalid user object'; + my $memc_only = delete $args{memcache_only} || 0; + my $db_only = delete $args{force_database} || 0; + confess 'extra/invalid arguments' if %args; + + # special case, we can disable loading friends for a user if there is a site + # problem or some other issue with this codebranch + return undef if $LJ::FORCE_EMPTY_FRIENDS{ $u->id }; + + # attempt memcache if allowed + unless ( $db_only ) { + my $memc = DW::User::Edges::WatchTrust::Loader::_trust_list_memc( $u ); + return $memc if $memc; + } + + # bail early if we are supposed to only hit memcache, this saves us from a + # potentially expensive database call in codepaths that are best-effort + return {} if $memc_only; + + # damn you memcache for not having our data + return DW::User::Edges::WatchTrust::Loader::_trust_list_db( $u ); +} +*LJ::User::trust_list = \&trust_list; + + +# returns hashref; +# +# { userid => +# { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN } +# } +# +# one entry in the hashref for everything the given user has in a particular trust +# group. you can specify the group by id or name. +# +# arguments is a hash of options +# id => 1, if set, get members of trust group id 1 +# name => "Foo Group", if set, get members of trust group "Foo Group" +# memcache_only => 1, if set, never hit database +# force_database => 1, if set, ALWAYS hit database (DANGER) +# +sub trust_group_list { + my ( $u, %args ) = @_; + $u = LJ::want_user( $u ) or confess 'invalid user object'; + my $memc_only = delete $args{memcache_only} || 0; + my $db_only = delete $args{force_database} || 0; + my $name = delete $args{name}; + my $id = delete $args{id}; + confess 'extra/invalid arguments' if %args; + confess 'need one of: id, name' unless $id || $name; + confess 'do not need both: id, name' if $id && $name; + + # special case, we can disable loading friends for a user if there is a site + # problem or some other issue with this codebranch + return undef if $LJ::FORCE_EMPTY_FRIENDS{ $u->id }; + + # load the user's groups + my $grp = $u->trust_groups( id => $id, name => $name ); + return {} unless $grp; + + # calculate mask to use later + my $mask = 1 << $grp->{groupnum}; + + # attempt memcache if allowed + unless ( $db_only ) { + my $memc = DW::User::Edges::WatchTrust::Loader::_trust_group_list_memc( $mask, $u ); + return $memc if $memc; + } + + # bail early if we are supposed to only hit memcache, this saves us from a + # potentially expensive database call in codepaths that are best-effort + return {} if $memc_only; + + # damn you memcache for not having our data + return DW::User::Edges::WatchTrust::Loader::_trust_group_list_db( $mask, $u ); +} +*LJ::User::trust_group_list = \&trust_group_list; + + +# returns hashref; +# +# { userid => +# { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN } +# } +# # one entry in the hashref for everything the given user is watching. # # arguments is a hash of options diff -r 8149c4258dbf -r eae6da291a54 cgi-bin/DW/User/Edges/WatchTrust/Loader.pm --- a/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm Fri Mar 06 07:33:37 2009 +0000 +++ b/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm Fri Mar 06 07:52:58 2009 +0000 @@ -116,8 +116,33 @@ sub _wt_userids { } +# helper to filter the _wt_list by a groupmask AND +sub _filter_wt_list { + my ( $mask, $raw ) = @_; + return {} unless $mask; # undef/0 = no matches! + return undef unless defined $raw && ref $raw eq 'HASH'; + return $raw unless keys %$raw; + + return + { + map { $_ => $raw->{$_} } + grep { $raw->{$_}->{groupmask} & $mask } + keys %$raw + }; +} + + +# helper, simply passes down to _wt_list_memc and filters +sub _watch_list_memc { return _filter_wt_list( 1 << 61, _wt_list_memc( @_ ) ); } +sub _watch_list_db { return _filter_wt_list( 1 << 61, _wt_list_db( @_ ) ); } +sub _trust_list_memc { return _filter_wt_list( 1, _wt_list_memc( @_ ) ); } +sub _trust_list_db { return _filter_wt_list( 1, _wt_list_db( @_ ) ); } +sub _trust_group_list_memc { return _filter_wt_list( shift(), _wt_list_memc( @_ ) ); } +sub _trust_group_list_db { return _filter_wt_list( shift(), _wt_list_db( @_ ) ); } + + # attempt to load a user's watch list from memcache -sub _watch_list_memc { +sub _wt_list_memc { my $u = $_[0]; # variable setup @@ -129,7 +154,7 @@ sub _watch_list_memc { my @cols = qw/ to_userid fgcolor bgcolor groupmask showbydefault /; # first, check memcache - my $memkey = [$userid, "watch_list:$userid"]; + my $memkey = [$userid, "wt_list:$userid"]; my $memdata = LJ::MemCache::get($memkey); return undef unless $memdata; @@ -159,13 +184,13 @@ sub _watch_list_memc { # attempt to load a user's watch list from the database -sub _watch_list_db { +sub _wt_list_db { my $u = $_[0]; my $userid = $u->id; my $dbh = LJ::get_db_writer(); - my $lockname = "get_watch_list:$userid"; + my $lockname = "get_wt_list:$userid"; my $release_lock = sub { LJ::release_lock($dbh, "global", $lockname); return $_[0]; @@ -176,7 +201,7 @@ sub _watch_list_db { return {} unless $lock; # in lock, try memcache - my $memc = _watch_list_memc( $u ); + my $memc = _wt_list_memc( $u ); return $release_lock->( $memc ) if $memc; # we are now inside the lock, but memcache was empty, so we must query @@ -184,7 +209,7 @@ sub _watch_list_db { # memcache data info my $ver = 2; # memcache data version - my $memkey = [$userid, "watch_list:$userid"]; + my $memkey = [$userid, "wt_list:$userid"]; my $packfmt = "NH6H6QC"; # pack format my $packlen = 19; # length of $packfmt @@ -195,7 +220,7 @@ sub _watch_list_db { # try the SQL on the master database my $sth = $dbh->prepare( 'SELECT to_userid, fgcolor, bgcolor, groupmask, showbydefault ' . - 'FROM wt_edges WHERE from_userid = ? AND groupmask & 1<<61' ); + 'FROM wt_edges WHERE from_userid = ?' ); $sth->execute( $userid ); confess $dbh->errstr if $dbh->err; --------------------------------------------------------------------------------