head=> body<= " unless LJ::text_in(\%GET) && LJ::text_in(\%POST); my $did_post = LJ::did_post(); my $remote = LJ::get_remote(); my $table = sub { $_[0]->{'journaltype'} eq 'C' ? 'comminterests' : 'userinterests' }; if (!$did_post && $GET{'view'} eq "popular") { return $ML{'.popular.disabled'} if $LJ::DISABLED{'interests-popular'}; my $ret = ""; $ret .= ""; my $dbr = LJ::get_db_reader(); my $sth = $dbr->prepare("SELECT statkey, statval FROM stats WHERE ". "statcat=? ORDER BY statval DESC, statkey ASC"); $sth->execute('pop_interests'); return "Sorry, interest data currently unavailable." unless $sth->rows(); $ret .= "

"; while (my ($int, $count) = $sth->fetchrow_array) { next if ($count == 1); LJ::text_out(\$int); my $eint = LJ::eurl($int); $ret .= ""; } $ret .= "
$ML{'.interest'}$ML{'.count'}
$int$count
"; return $ret; } if ((!$did_post && $GET{'mode'} eq "add" && $GET{'intid'}) || ($did_post && $POST{'mode'} eq "add" && $POST{'intid'})) { my $intid = $did_post ? $POST{'intid'}+0 : $GET{'intid'}+0; my $ret; unless ($remote) { $ret .= ""; return $ret; } # force them to either come from the interests.bml page, or have posted the request. # if both fail, ask them to confirm with a post form. my $dbr = LJ::get_db_reader(); unless ($did_post || BML::get_client_header('Referer') =~ /^\Q$LJ::SITEROOT\E\/interests\.bml\?/) { my ($int) = $dbr->selectrow_array("SELECT interest FROM interests WHERE intid=?", undef, $intid); LJ::text_out(\$int); $ret .= ""; $ret .= " $int}); $ret .= "

"; $ret .= LJ::html_hidden('mode' => 'add', 'intid' => $intid); $ret .= LJ::html_submit(undef, BML::ml(".add.btn.text", {'interest' => $int})); $ret .= "
p?>"; return $ret; } my $rints = LJ::get_interests($remote); my $count = scalar(@$rints); if ($count >= 150) { $ret .= " "150"}) ." p?>"; return $ret; } my $dbh = LJ::get_db_writer(); my $uitable = $table->($remote); $dbh->do("INSERT INTO $uitable (userid, intid) VALUES (?, ?)", undef, $remote->{'userid'}, $intid); LJ::memcache_kill($remote, "intids"); unless ($dbh->err) { $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid=?", undef, $intid); } # if a community, remove any old rows from userinterests if ($remote->{'journaltype'} eq 'C') { $dbh->do("DELETE FROM userinterests WHERE userid=?", undef, $remote->{'userid'}); } $ret .= ""; return $ret; } if (!$did_post && $GET{'mode'} eq "findsim_do") { return $ML{'error.tempdisabled'} if $LJ::DISABLED{'interests-findsim'}; return $ML{'.findsim_do.account.notallowed'} unless LJ::get_cap($remote, "findsim"); my $ret = ""; my $u = LJ::load_user($GET{'user'}); return "" unless $u; my @ints; my %intcount; my $dbr = LJ::get_db_reader(); my $sth = $dbr->prepare("SELECT i.intid, i.intcount FROM userinterests ui, interests i ". "WHERE ui.userid=? AND ui.intid=i.intid"); $sth->execute($u->{'userid'}); while (my ($intid, $count) = $sth->fetchrow_array) { push @ints, $intid; $intcount{$intid} = $count || 1; } unless (@ints) { my $msg = BML::ml('.findsim_do.notdefined', { 'user' => LJ::ljuser($u) }); return ""; } my %pt_count; my %pt_weight; foreach my $int (@ints) { # the magic's in this limit clause. that's what makes this work. perfect # results? no. but who cares if somebody that lists "music" or "women" # doesn't get an extra point towards matching you. we care about more unique interests. my $sth = $dbr->prepare("SELECT userid FROM userinterests WHERE intid=? LIMIT 500"); $sth->execute($int); while (my $uid = $sth->fetchrow_array) { next if $uid == $u->{'userid'}; $pt_weight{$uid} += (1 / log($intcount{$int}+1)); $pt_count{$uid}++; } } my %magic; # balanced points foreach (keys %pt_count) { $magic{$_} = $pt_weight{$_}*10 + $pt_count{$_}; } my @matches = sort { $magic{$b} <=> $magic{$a} } keys %magic; if (@matches > 150) { @matches = @matches[0..149]; } my $sth = $dbr->prepare("SELECT userid, user FROM useridmap WHERE userid IN (" . join(",",@matches) . ")"); $sth->execute; my %username; while (my ($id, $name) = $sth->fetchrow_array) { $username{$id} = $name; } unless (@matches) { return " LJ::ljuser($u)}) ." p?>"; } $ret .= " LJ::ljuser($u)}) ." p?>"; $ret .= "

"; my $count; foreach my $uid (@matches) { $count++; $ret .= "", $magic{$uid}); } $ret .= "
#$ML{'User'}$ML{'.findsim_do.magic'}
$count"; $ret .= LJ::ljuser($username{$uid}); $ret .= sprintf("%.3f

"; $ret .= ""; return $ret; } if (!$did_post && $GET{'mode'} eq "enmasse") { return LJ::bad_input($ML{'.error.enmasse.mustlogin'}) unless $remote; my $authas = $GET{'authas'} || $remote->{'user'}; my $u = LJ::get_authas_user($authas); return LJ::bad_input(BML::ml('.error.enmasse.noaccess', {'user' => LJ::ljuser($authas)})) unless $u; my $altauthas = $remote->{'user'} ne $u->{'user'}; my $getextra = $altauthas ? "?authas=$u->{'user'}" : ''; my $userid = $u->{'userid'}; my $username = $u->{'user'}; my $fromu = LJ::load_user($GET{'fromuser'} || $username); my %uint; my %fromint; my $fints = LJ::get_interests($fromu); foreach (@$fints) { $fromint{$_->[1]} = $_->[0]+0; } return "" unless %fromint; my $ret = ""; $ret .= LJ::html_hidden(mode => 'enmasse', fromuser => $fromu->{'user'}); $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); $ret .= " p?>
"; $ret .= "{'userid'} == $fromu->{'userid'}) { %uint = %fromint; $ret .= $ML{'.enmasse.body.you'}; } else { my $in = join (",", map { $fromint{$_} } keys %fromint); my $uints = LJ::get_interests($u); foreach (@$uints) { $uint{$_->[1]} = $_->[0]; } if ($altauthas) { $ret .= BML::ml('.enmasse.body.other_authas', { 'user' => LJ::ljuser($fromu), 'target' => LJ::ljuser($u) }); } else { $ret .= BML::ml('.enmasse.body.other', { 'user' => LJ::ljuser($fromu) }); } } $ret .= " p?>
"; $ret .= ""; my @fromintsorted = sort keys %fromint; my $cols = 3; my $rows = int((scalar(@fromintsorted) + $cols - 1) / $cols); for (my $i = 0; $i < $rows; $i++) { $ret .= ""; for (my $j = 0; $j < $cols; $j++) { my $index = $rows * $j + $i; if ($index < scalar(@fromintsorted)) { my $checked = $uint{$fromintsorted[$index]} ? 1 : undef; $ret .= ""; } else { $ret .= ""; } } $ret .= ""; } $ret .= "
"; $ret .= LJ::html_check({name => "int_$fromint{$fromintsorted[$index]}", id => "int_$fromint{$fromintsorted[$index]}", selected => $checked, value => 1}); my $bold1 = $checked ? "" : ""; my $bold2 = $checked ? "" : ""; $ret .= " 
"; $ret .= LJ::html_hidden('mode', 'enmasse_do'); $ret .= LJ::html_hidden('fromuser', $fromu->{'user'}); $ret .= LJ::html_hidden('allintids', join (",", values %fromint)); $ret .= "
"; return $ret; } if ($did_post && $POST{'mode'} eq "enmasse_do") { return "" unless $remote; my $authas = $GET{'authas'} || $remote->{'user'}; my $u = LJ::get_authas_user($authas); return LJ::bad_input($ML{'.error.noauth'}) unless $u; my $uitable = $table->($u); my %uint; my $intcount = 0; my $uints = LJ::get_interests($u); foreach (@$uints) { $uint{$_->[0]} = $_->[1]; # uint{intid} = interest $intcount++; } my @fromints = map { $_+0 } split (/\s*,\s*/, $POST{'allintids'}); my @todel; my @toadd; foreach my $fromint (@fromints) { next unless $fromint > 0; # prevent adding zero or negative intid push (@todel, $fromint) if $uint{$fromint} && !$POST{'int_'.$fromint}; push (@toadd, $fromint) if !$uint{$fromint} && $POST{'int_'.$fromint}; } my ($deleted, $added, $toomany) = (0, 0, 0); if (@todel) { my $intid_in = join(",", @todel); my $dbh = LJ::get_db_writer(); $dbh->do("DELETE FROM $uitable WHERE userid=? AND intid IN ($intid_in)", undef, $u->{'userid'}); $dbh->do("UPDATE interests SET intcount=intcount-1 WHERE intid IN ($intid_in)"); $deleted = 1; } if (@toadd) { if ($intcount + scalar @toadd > 150) { $toomany = 1; } else { my $dbh = LJ::get_db_writer(); my $sqlp = "(?,?)" . (",(?,?)" x (scalar(@toadd) - 1)); my @bindvars = map { ($u->{'userid'}, $_) } @toadd; $dbh->do("REPLACE INTO $uitable (userid, intid) VALUES $sqlp", undef, @bindvars); my $intid_in = join(",", @toadd); $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid IN ($intid_in)"); $added = 1; } } # if a community, remove any old rows from userinterests if ($u->{'journaltype'} eq 'C') { my $dbh = LJ::get_db_writer(); $dbh->do("DELETE FROM userinterests WHERE userid=?", undef, $u->{'userid'}); } my $ret = " 150}) : $ML{'.results.deleted'}; } else { $ret .= $added ? $ML{'.results.added'} : $toomany ? BML::ml('.results.toomany', {'intcount' => 150}) : $ML{'.results.nothing'}; } $ret .= " p?> '/userinfo.bml?user=' . $u->{'user'} }); $ret .= " " . BML::ml('.results.goback', { 'url' => '/userinfo.bml?user=' . LJ::eurl($POST{'fromuser'}), 'user' => LJ::ljuser($POST{'fromuser'}), }) if ($POST{'fromuser'} ne "" && $POST{'fromuser'} ne $u->{'user'}); $ret .= " p?>"; LJ::memcache_kill($u, "intids"); return $ret; } if (!$did_post && ($GET{'intid'} || $GET{'int'})) { my $sth; my $dbr = LJ::get_db_reader(); my ($interest, $intid, $intcount); if ($GET{'intid'}) { ($interest, $intid, $intcount) = $dbr->selectrow_array("SELECT interest, intid, intcount FROM interests WHERE intid=?", undef, $GET{'intid'}); } else { ($interest, $intid, $intcount) = $dbr->selectrow_array("SELECT interest, intid, intcount FROM interests WHERE interest=?", undef, $GET{'int'}); } return "" unless $interest; $intid += 0; my $ret = ""; ### hook LJ::run_hooks("interests_bml", { 'intid' => $intid, 'int' => $interest, 'ret' => \$ret, }); ### communities my $LIMIT = 500; unless ($LJ::DISABLED{'interests-community'}) { my @uids; $sth = $dbr->prepare("SELECT userid FROM comminterests WHERE intid=? LIMIT $LIMIT"); $sth->execute($intid); push @uids, $_ while $_ = $sth->fetchrow_array; my $us = LJ::load_userids(@uids); my @cl = grep { $_->{statusvis} eq "V" } values %$us; @cl = sort { $a->{user} cmp $b->{user} } @cl; my $count = @cl; my $list; foreach (@cl) { my $name = $_->{name}; LJ::text_out(\$name); $list .= "
  • " . LJ::ljuser($_) . " - " . LJ::ehtml($name) . "
  • "; } if (@cl) { my $matchcount = BML::ml(@cl == 1 ? ".match" : ".matches", {'count' => $count }); $ret .= " $interest}) ." p?>"; $ret .= "

    $matchcount

    "; } } ##### users $ret .= " $interest}); if ($remote) { $ret .= " " . BML::ml(".addint", {'qintid' => $intid}); } $ret .= " $ML{'.morestuff'} p?>"; my @uids; $sth = $dbr->prepare("SELECT userid FROM userinterests WHERE intid=? LIMIT $LIMIT"); $sth->execute($intid); push @uids, $_ while $_ = $sth->fetchrow_array; my $us = LJ::load_userids(@uids); my @ul = grep { $_->{statusvis} eq "V" && $_->{journaltype} ne "C" } values %$us; @ul = sort { $a->{user} cmp $b->{user} } @ul; my $count = @ul; my $list; foreach (@ul) { my $name = $_->{name}; LJ::text_out(\$name); $list .= "
  • " . LJ::ljuser($_) . " - " . LJ::ehtml($name) . "
  • "; } my $matchcount = BML::ml(@ul == 1 ? ".match" : ".matches", { 'count' => $count }); $ret .= "

    $matchcount

    "; return $ret; } my $ret = ""; $ret .= ""; $ret .= ""; unless ($LJ::DISABLED{'interests-popular'}) { $ret .= ""; } $ret .= ""; $ret .= ""; if (!$LJ::DISABLED{'interests-findsim'} && $remote && LJ::get_cap($remote, "findsim")) { $ret .= ""; } $ret .= ""; $ret .= ""; $ret .= "
    "; $ret .= "$ML{'.interests.viewpop'}
    $ML{'.interested.in'}
    "; $ret .= LJ::html_text({name => 'int', size => 20}) . " "; $ret .= LJ::html_submit(undef, $ML{'.interested.btn.find'}); $ret .= "
    $ML{'.interests.findsim'}
    "; $ret .= LJ::html_hidden('mode', 'findsim_do'); $ret .= LJ::html_text({name => 'user', value => $remote->{'user'}, size => 20}) . " "; $ret .= LJ::html_submit(undef, $ML{'.interested.btn.find'}); $ret .= "
    $ML{'.enmasse.intro'}
    "; $ret .= LJ::html_text({name => 'fromuser', size => 20}) . " "; $ret .= LJ::html_submit(undef, $ML{'.enmasse.btn'}); $ret .= LJ::html_hidden('mode', 'enmasse'); $ret .= "
    "; $ret .= $ML{'.nointerests.text'}; return $ret; } _code?> <=body page?> link: htdocs/interests.bml, htdocs/editinfo.bml post: htdocs/interests.bml form: htdocs/interests.bml _c?>