fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2011-10-18 03:48 pm

[dw-free] Search for several interests at once

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

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

Search for up to 3 interests at a time over on /interests. This is an AND
search -- that is, search for all users and communities that have interest A
and interest B (not: search for all users that either have interest A or
have interest B)

Patch by [personal profile] kareila.

Files modified:
  • bin/upgrading/en.dat
  • cgi-bin/DW/Controller/Search/Interests.pm
  • views/interests/int.tt
  • views/interests/int.tt.text
--------------------------------------------------------------------------------
diff -r bcf5b08d50e7 -r a6aa1d25ea3c bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Tue Oct 18 10:21:14 2011 -0500
+++ b/bin/upgrading/en.dat	Tue Oct 18 23:47:19 2011 +0800
@@ -1859,6 +1859,8 @@
 
 interests.error.nointerests=The selected account hasn't specified any interests.
 
+interests.error.toomany=You can't search for more than [[num]] interests at a time.
+
 interests.findsim_do.account.notallowed=Your account type doesn't let you use this tool.
 
 interests.findsim_do.nomatch=Nobody similar to [[user]].
diff -r bcf5b08d50e7 -r a6aa1d25ea3c cgi-bin/DW/Controller/Search/Interests.pm
--- a/cgi-bin/DW/Controller/Search/Interests.pm	Tue Oct 18 10:21:14 2011 -0500
+++ b/cgi-bin/DW/Controller/Search/Interests.pm	Tue Oct 18 23:47:19 2011 +0800
@@ -282,7 +282,8 @@
                 $e_int = LJ::ehtml( $interest ? $interest :
                                     substr( $check_int, 0, LJ::CMAX_SITEKEYWORD ) );
 
-                $rv->{warn_toolong} =
+                $rv->{warn_toolong} = ( $rv->{warn_toolong} ?
+                                        $rv->{warn_toolong} . "<br />" : '' ) .
                     LJ::Lang::ml( 'interests.error.longinterest',
                                   { sitename => $LJ::SITENAMESHORT,
                                     old_int => $e_int_long, new_int => $e_int,
@@ -292,21 +293,53 @@
             return $e_int;
         };
 
-        my $intarg = LJ::utf8_lc ( $args->{int} );
-        my $intid = $args->{intid} ? $args->{intid} + 0 :
-            LJ::get_sitekeyword_id( $intarg, 0 ) || 0;
-        my ( $interest, $intcount ) = LJ::get_interest( $intid );
-
-        my $check_int = $intarg || $interest;
-        if ( LJ::Hooks::run_hook( "interest_search_ignore",
-                                  query => $check_int, intid => $intid ) ) {
-            return error_ml( 'interests.error.ignored' );
+        my ( @intids, @intargs );
+        if ( $args->{intid} ) {
+            @intids = ( $args->{intid} + 0 );
+        } else {
+            @intargs = LJ::interest_string_to_list( $args->{int} );
+            @intids = map { LJ::get_sitekeyword_id( $_, 0 ) || 0 } @intargs;
         }
 
-        $rv->{e_int} = $trunc_check->( $check_int, $interest );
-        $rv->{interest} = $interest;
-        $rv->{intid} = $intid;
-        $rv->{intcount} = $intcount;
+        my $max_search = 3;
+        if ( scalar @intids > $max_search ) {
+            return error_ml( 'interests.error.toomany', { num => $max_search } );
+        }
+
+        my ( @intdata, @no_users, @not_interested );
+        my $index = 0;  # for referencing @intargs
+        my $remote_interests = $remote ? $remote->interests : {};
+
+        foreach my $intid ( @intids ) {
+            my $intarg = @intargs ? $intargs[$index++] : '';
+            my ( $interest, $intcount ) = LJ::get_interest( $intid );
+            my $check_int = $intarg || $interest;
+
+            if ( LJ::Hooks::run_hook( "interest_search_ignore",
+                                      query => $check_int,
+                                      intid => $intid ) ) {
+                return error_ml( 'interests.error.ignored' );
+            }
+
+            my $e_int = $trunc_check->( $check_int, $interest );
+            push @intdata, $e_int;
+            push @no_users, $e_int unless $intcount;
+
+            $rv->{allcount} = $intcount if scalar @intids == 1;
+
+            # check to see if the remote user already has the interest
+            push @not_interested, { int => $e_int, intid => $intid }
+                if defined $interest && ! $remote_interests->{$interest};
+        }
+
+        $rv->{interest} = join ', ', @intdata;
+        $rv->{query_count} = scalar @intdata;
+        $rv->{no_users} = join ', ', @no_users;
+        $rv->{no_users_count} = scalar @no_users;
+        $rv->{not_interested} = \@not_interested;
+
+        # if any one interest is unused, the search can't succeed
+        undef @intids if @no_users;
 
         # filtering by account type
         my @type_args = ( 'none', 'P', 'C', 'I' );
@@ -330,7 +363,16 @@
                         I => 'nocomms', F => 'circle' );
         $type_opts = { $opt_map{$type} => 1 } if defined $opt_map{$type};
 
-        my @uids = LJ::users_with_all_ints( [$intid], $type_opts );
+        my @uids = LJ::users_with_all_ints( \@intids, $type_opts );
+
+        # determine the count of the full set for comparison
+        # (already set to intcount, unless we have multiple ints)
+        if ( $opt_map{$type} ) {
+            $rv->{allcount} ||= scalar LJ::users_with_all_ints( \@intids );
+        } else {
+            # we just did the full search; count the existing list
+            $rv->{allcount} ||= scalar @uids;
+        }
 
         # limit results to 500 most recently updated journals
         if ( scalar @uids > 500 ) {
@@ -365,7 +407,7 @@
         my @ul = sort { $def_upd->($b) <=> $def_upd->($a) || $a->user cmp $b->user }
                  grep { $_ && $typefilter->( $_ ) && $should_show->( $_ ) }
                  values %$us;
-        $rv->{type_count} = scalar @ul if $intcount != scalar @ul;
+        $rv->{type_count} = scalar @ul if $rv->{allcount} != scalar @ul;
         $rv->{comm_count} = 1 if $type_opts->{nocomms};  # doesn't count
 
         if ( @ul ) {
@@ -400,10 +442,6 @@
             $rv->{data} = \@data;
         }
 
-        # check to see if the remote user already has the interest
-        $rv->{not_interested} = ! $remote->interests->{$interest}
-            if $remote && defined $interest;
-
         return DW::Template->render_template( 'interests/int.tt', $rv );
     }
 
diff -r bcf5b08d50e7 -r a6aa1d25ea3c views/interests/int.tt
--- a/views/interests/int.tt	Tue Oct 18 10:21:14 2011 -0500
+++ b/views/interests/int.tt	Tue Oct 18 23:47:19 2011 +0800
@@ -32,8 +32,7 @@
 <table summary=''><tr valign='middle'><td class='findandmodify'>
 [% 'interests.interested.in' | ml %]</td><td class='findandmodify'>
 <form method='get' action='interests'>
-<input type="text" name="int" size="20" value="
-[%- interest ? interest : e_int %]" />&nbsp;
+<input type="text" name="int" size="20" value="[% interest # escaped in the controller %]" />&nbsp;
 <input type='submit' value='[% "interests.interested.btn" | ml %]' />
 </form></td></tr>
 <tr valign='middle'><td class='findandmodify'>
@@ -43,32 +42,32 @@
 <input type="text" name="fromuser" size="20" />&nbsp;
 <input type='submit' value='[% "interests.enmasse.btn" | ml %]' />
 </form></td></tr></table>
-<h1>[% ".header" | ml(interest = e_int) %]</h1>
-<div class='typefilter'>[% '.filterlink.label' | ml %]&nbsp;
-[%- FOREACH type = type_list -%]
-    [%- link = type_link(type) -%]
-    [%- IF type != 'none' ; '&nbsp;|&nbsp;' ; END -%]
-    [%- IF link %]<a href="[% link | html %]">[% END -%]
-    [%- ".filterlink.$type" | ml -%]
-    [%- IF link ; '</a>' ; END -%]
-[%- END -%]
-</div>
-[%- IF intcount -%]
-    <p class='interestinfo'>
-    [%- IF not_interested -%]
-        [%- '.addint2' | ml(aopts = "href='$site.root/interests?mode=add&amp;intid=$intid'") -%]
+<h1>[% ".header" | ml(interest = interest) %]</h1>
+[%- IF allcount -%]
+  <div class='typefilter'>[% '.filterlink.label' | ml %]&nbsp;
+    [%- FOREACH type = type_list;
+        link = type_link(type);
+        IF type != 'none' ; '&nbsp;|&nbsp;' ; END;
+        IF link %]<a href="[% link | html %]">[% END;
+        ".filterlink.$type" | ml;
+        IF link ; '</a>' ; END;
+        END -%]
+  </div>
+    [%- FOREACH not_interested -%]
+        <p class='interestinfo'>
+        [%- '.addint3' | ml(int = int, aopts = "href='$site.root/interests?mode=add&amp;intid=$intid'") -%]</p>
     [%- END -%]
-    [% '.morestuff2' | ml(aopts = "href='$site.root/interests'") %]</p>
     [%- UNLESS comm_count -%]
         <p class='interestinfo'>
-        [%- '.nocomms' | ml(aopts = "href='$site.root/community/create'",
-                            int = e_int) %]</p>
+        [%- '.nocomms2' | ml(aopts = "href='$site.root/community/create'", num = query_count) %]</p>
     [%- END -%]
+    <p class='interestinfo'>
+    [% '.morestuff2' | ml(aopts = "href='$site.root/interests'") %]</p>
     <p class='matches'><b>
     [%- IF type_count -%]
-        [% '.filtered' | ml(num = intcount, count = type_count) %]</p>
+        [% '.filtered' | ml(num = allcount, count = type_count) %]</p>
     [%- ELSE -%]
-        [% '.matches2' | ml(num = intcount) %]
+        [% '.matches2' | ml(num = allcount) %]
     [%- END -%]
     </b></p>
     [%- IF data -%]
@@ -95,10 +94,17 @@
     [%- END -%]
 [%- ELSE -%]
     <p class='interestinfo'>
-    [%- '.nocomms' | ml(aopts = "href='$site.root/community/create'",
-                        int = e_int) %]</p>
+    [%- '.nocomms2' | ml(aopts = "href='$site.root/community/create'", num = query_count) %]</p>
     <p class='interestinfo'>
-    [%- '.nousers' | ml(int = e_int,
-        aopts_add = "href='$site.root/interests?mode=addnew&amp;keyword=$e_int'",
-        aopts_int = "href='$site.root/interests'") %]</p>
+    [%- IF no_users -%]
+        [%- '.nousers2' | ml(aopts = "href='$site.root/interests?mode=addnew&amp;keyword=$no_users'", num = no_users_count) %]</p>
+    [%- ELSE -%]
+        [%- '.notall' | ml %]</p>
+        [%- FOREACH not_interested -%]
+            <p class='interestinfo'>
+            [%- '.addint3' | ml(int = int, aopts = "href='$site.root/interests?mode=add&amp;intid=$intid'") -%]</p>
+        [%- END -%]
+    [%- END -%]
+    <p class='interestinfo'>
+    [% '.morestuff2' | ml(aopts = "href='$site.root/interests'") %]</p>
 [%- END -%]
diff -r bcf5b08d50e7 -r a6aa1d25ea3c views/interests/int.tt.text
--- a/views/interests/int.tt.text	Tue Oct 18 10:21:14 2011 -0500
+++ b/views/interests/int.tt.text	Tue Oct 18 23:47:19 2011 +0800
@@ -1,5 +1,5 @@
 ;; -*- coding: utf-8 -*-
-.addint2=If you're also interested in this, would you like to be <a [[aopts]]>added to this list</a>?
+.addint3=If you're also interested in "<b>[[int]]</b>", would you like to <a [[aopts]]>add it to your profile</a>?
 
 .filtered=[[num]] [[?num|match|matches]], showing [[count]] [[?count|result|results]]:
 
@@ -25,10 +25,12 @@
 
 .morestuff2=You can find more fun stuff on the <a [[aopts]]>interests page</a>.
 
-.nocomms=There are no communities interested in "<b>[[int]]</b>." You can <a [[aopts]]>create one</a>!
+.nocomms2=There are no communities matching the [[?num|interest|interests]] you specified, but you can <a [[aopts]]>create one</a>!
 
 .nomatch=No matching users for the specified account type. <a href="[[link]]">View all accounts with this interest.</a>
 
-.nousers=There are no users interested in "<b>[[int]]</b>". If you are interested in this, <a [[aopts_add]]>click here to add the interest to your profile</a>. More fun stuff can be found on the <a [[aopts_int]]>interests page</a>.
+.notall=There are no users matching all of the interests you specified.  You may want to modify your search.
+
+.nousers2=No one currently has [[num]] of the interests you're searching for. If you're interested, <a [[aopts]]>click here to add [[?num|the new interest|all of the new interests]] to your profile</a>.
 
 .title=Interests
--------------------------------------------------------------------------------