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 .= "
$ML{'.interest'} | $ML{'.count'} |
";
while (my ($int, $count) = $sth->fetchrow_array)
{
next if ($count == 1);
LJ::text_out(\$int);
my $eint = LJ::eurl($int);
$ret .= "$int | $count |
";
}
$ret .= "
";
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 .= " 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 .= "# | $ML{'User'} | $ML{'.findsim_do.magic'} |
";
my $count;
foreach my $uid (@matches)
{
$count++;
$ret .= "$count | ";
$ret .= LJ::ljuser($username{$uid});
$ret .= sprintf(" | %.3f |
", $magic{$uid});
}
$ret .= "
";
$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?>";
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 .= "$ML{'.interests.viewpop'} |
";
}
$ret .= "$ML{'.interested.in'} | ";
$ret .= " |
";
if (!$LJ::DISABLED{'interests-findsim'} && $remote && LJ::get_cap($remote, "findsim")) {
$ret .= "$ML{'.interests.findsim'} | |
";
}
$ret .= "$ML{'.enmasse.intro'} | ";
$ret .= " |
";
$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?>