#!/usr/bin/perl # require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl"; use strict; package LJ::Portal; use vars qw(%box %colname); %colname = ("left" => "Left Sidebar", "main" => "Main Area", "right" => "Right Sidebar", "moz" => "Mozilla Sidebar", ); # was using "use constant" here but the error logs filled up with # warnings about redefinitions of subroutines. (constants are subs... great, perl.) my $BOX_NAME = 0; my $BOX_ARGS = 1; my $BOX_POS = 2; my $BOX_DIRTY = 3; sub get_box_size { my $loc = shift; return $loc eq "main" ? "large" : "small"; } sub get_box_types { my $loc = shift; my $size = get_box_size($loc); return map { $_, $box{$_}->{'name'} } grep { $box{$_}->{$size} } sort keys %box; } sub construct_page { my $opts = shift; my $body = $opts->{'body'}; my $remote = $opts->{'remote'}; my $puri = $opts->{'puri'}; $opts->{'border'} += 0; my %tdopts = ('main' => "", 'right' => "width=180", 'left' => "width=180", ); my $portopts = load_portopts($remote); $$body .= "{'border'} cellpadding=3 width=100% height=500>\n"; $$body .= "\n"; foreach my $loc (@LJ::PORTAL_COLS) { next if ($loc eq "moz"); $$body .= "\n"; } $$body .= "\n"; $$body .= "
\n"; $portopts->{$loc} ||= []; foreach my $pbox (@{$portopts->{$loc}}) { my $bname = $pbox->[$BOX_NAME]; my $bargs = $pbox->[$BOX_ARGS]; next unless (ref $box{$bname}->{'handler'} eq "CODE"); my $args = {}; LJ::decode_url_string(\$bargs, $args); my $box = $box{$bname}; $box->{'key'} = $bname; # so we don't have to set it explicitly $box->{'args'} = $args; $box->{'loc'} = $loc; $box->{'pos'} = "$pbox->[$BOX_POS]"; $box->{'uniq'} = "$loc$pbox->[$BOX_POS]"; $box{$bname}->{'handler'}->($remote, $opts, $box); } $$body .= "
\n"; if ($opts->{'onload'}) { ${$opts->{'bodyopts'}} .= "onLoad=\"" . join('', keys %{$opts->{'onload'}}) . "\""; } } sub load_portopts { my $remote = shift; my $dbr = LJ::get_db_reader(); my $portopts; # if user is logged in, see if they've defined their portal box settings: if ($remote) { my $sth = $dbr->prepare("SELECT loc, pos, boxname, boxargs FROM portal WHERE userid=$remote->{'userid'} ORDER BY loc, pos"); $sth->execute; while (my $row = $sth->fetchrow_hashref) { push @{$portopts->{$row->{'loc'}}}, [ $row->{'boxname'}, $row->{'boxargs'}, $row->{'pos'} ]; } } # if the user isn't logged in, or they haven't defined their portal boxes, # then give them the defaults: unless ($portopts) { if ($remote) { $portopts = $LJ::PORTAL_LOGGED_IN; } else { $portopts = $LJ::PORTAL_LOGGED_OUT; } ## set the 'pos' argument on each box arrayref ## so it doesn't have to be set explicitly in ljconfig.pl, which would be tedious. ## also, set the dirty flag to true, so a subsequent save will change it foreach my $loc (keys %$portopts) { for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { $portopts->{$loc}->[$i]->[$BOX_POS] = $i+1; $portopts->{$loc}->[$i]->[$BOX_DIRTY] = 1; } } } return $portopts; } sub count_boxes { my $portopts = shift; my $count = 0; foreach my $loc (keys %$portopts) { for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { my $box = $portopts->{$loc}->[$i]; if ($box->[$BOX_NAME]) { $count++; } } } return $count; } # FIXME: portal info should be clustered! sub save_portopts { my $remote = shift; my $portopts = shift; my $dbh = LJ::get_db_writer(); my $userid = $remote->{'userid'}+0; return unless $userid; my @delsql; my $sql; foreach my $loc (keys %$portopts) { for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { my $box = $portopts->{$loc}->[$i]; next unless ($box->[$BOX_DIRTY]); my $qloc = $dbh->quote($loc); my $qpos = $box->[2] + 0; if ($box->[$BOX_NAME]) { # modifying my $qboxname = $dbh->quote($box->[$BOX_NAME]); my $qboxargs = $dbh->quote($box->[$BOX_ARGS]); $sql ||= "REPLACE INTO portal (userid, loc, pos, boxname, boxargs) VALUES "; $sql .= "($userid, $qloc, $qpos, $qboxname, $qboxargs),"; } else { # deleting push @delsql, "DELETE FROM portal WHERE userid=$userid AND loc=$qloc AND pos=$qpos"; } $box->[$BOX_DIRTY] = 0; } } if ($sql) { chop $sql; $dbh->do($sql); } foreach (@delsql) { $dbh->do($_); } } sub delete_box { my $portopts = shift; my $loc = shift; my $pos = shift; my $bname = shift; return unless (defined $portopts->{$loc}->[$pos-1]); my $box = $portopts->{$loc}->[$pos-1]; return unless ($box->[$BOX_NAME] eq $bname); # time to delete it... move everything else up. my $locsize = scalar(@{$portopts->{$loc}}); # else, move everything else up, and mark the file one dirty; for (my $i=$pos; $i < $locsize; $i++) { $portopts->{$loc}->[$i-1] = $portopts->{$loc}->[$i]; $portopts->{$loc}->[$i-1]->[$BOX_POS] = $i; $portopts->{$loc}->[$i-1]->[$BOX_DIRTY] = 1; } # final one is dirty and marked for deletion $portopts->{$loc}->[$locsize-1] = [ "", "", $locsize, 1]; } sub move_box { my $portopts = shift; my $loc = shift; my $pos = shift; my $bname = shift; my $op = shift; return unless (defined $portopts->{$loc}->[$pos-1]); my $box = $portopts->{$loc}->[$pos-1]; return unless ($box->[$BOX_NAME] eq $bname); # how many are in that column? my $locsize = scalar(@{$portopts->{$loc}}); # can't move top up or bottom down. return if ($op eq "u" && $pos == 1); return if ($op eq "d" && $pos == $locsize); # destination position my $dpos = $pos + ($op eq "u" ? -1 : 1); # does that location exist to swap with? return unless (defined $portopts->{$loc}->[$dpos-1]); # swap locations! ($portopts->{$loc}->[$dpos-1], $portopts->{$loc}->[$pos-1]) = ($portopts->{$loc}->[$pos-1], $portopts->{$loc}->[$dpos-1]); # set their locations and dirty flags foreach my $p ($pos, $dpos) { $portopts->{$loc}->[$p-1]->[$BOX_POS] = $p; $portopts->{$loc}->[$p-1]->[$BOX_DIRTY] = 1; } } sub make_box_modify_form { my $portopts = shift; my $loc = shift; my $pos = shift; return "" unless (defined $portopts->{$loc}->[$pos-1]); my $box = $portopts->{$loc}->[$pos-1]; my $curargs = {}; LJ::decode_url_string(\$box->[$BOX_ARGS], $curargs); my $ret = ""; foreach my $opt (@{$box{$box->[$BOX_NAME]}->{'opts'}}) { unless ($ret) { $ret .= "
"; } $ret .= "

$opt->{'name'}: "; my $key = $opt->{'key'}; if ($opt->{'type'} eq "select") { $ret .= LJ::html_select({ 'name' => "arg_$key", 'selected' => $curargs->{$key}, 'noescape' => 1, }, @{$opt->{'values'}}); } if ($opt->{'type'} eq "check") { $ret .= LJ::html_check({ 'name' => "arg_$key", 'selected' => $curargs->{$key}, 'value' => 1, }); } if ($opt->{'type'} eq "text") { $ret .= LJ::html_text({ 'name' => "arg_$key", 'maxlength' => $opt->{'maxlength'}, 'size' => $opt->{'size'}, 'value' => $curargs->{$key}, }); } if ($opt->{'des'}) { $ret .= "
$opt->{'des'}"; } } if ($ret) { $ret .= "

"; $ret .= "

"; } return $ret; } sub modify_box { my $remote = shift; my $portopts = shift; my $loc = shift; my $pos = shift; my $form = shift; return "" unless (defined $portopts->{$loc}->[$pos-1]); my $box = $portopts->{$loc}->[$pos-1]; my $newargs; foreach my $opt (@{$box{$box->[$BOX_NAME]}->{'opts'}}) { if ($newargs) { $newargs .= "&"; } $newargs .= LJ::eurl($opt->{'key'}) . "=" . LJ::eurl($form->{"arg_$opt->{'key'}"}); $box->[$BOX_ARGS] = $newargs; $box->[$BOX_DIRTY] = 1; } save_portopts($remote, $portopts); return $newargs; } sub create_new_box { my ($portopts, $bname, $loc) = @_; my $defargs; foreach my $opt (@{$box{$bname}->{'opts'}}) { # if non-zero or non-blank default, remember it if ($opt->{'default'}) { $defargs .= "&" if ($defargs); $defargs .= LJ::eurl($opt->{'key'}) . "=" . LJ::eurl($opt->{'default'}); } } $portopts->{$loc} ||= []; my $size = scalar(@{$portopts->{$loc}}); push @{$portopts->{$loc}}, [ $bname, $defargs, $size+1, 1 ]; } sub make_box_link { my $form = shift; my $bname = $form->{'bname'}; my $args = ""; foreach my $arg (@{$box{$bname}->{'args'}}) { my $key = $arg->{'key'}; my $val = $form->{"arg_$key"}; if ($val) { $args .= "&$key=$val"; } } my $title = $box{$bname}->{'name'} . " ($LJ::SITENAME)"; return "$LJ::SITEROOT/portal/box.bml?bname=$bname$args"; } # XXXXXXXX DEAD / OLD sub make_mozilla_box { my $remote = shift; my $form = shift; my $opts = shift; my $bname = $form->{'bname'}; return "" unless (ref $box{$bname}->{'handler'} eq "CODE"); my $box = $box{$bname}; $box->{'key'} = $bname; $box->{'args'} = $form; $box->{'pos'} = "moz"; $box->{'loc'} = 1; $box->{'uniq'} = "moz1"; $box{$bname}->{'handler'}->($remote, $opts, $box); } sub make_mozilla_bar { my $remote = shift; my $form = shift; my $opts = shift; my $portopts = load_portopts($remote); my $loc = "moz"; foreach my $pbox (@{$portopts->{$loc}}) { my $bname = $pbox->[$BOX_NAME]; my $bargs = $pbox->[$BOX_ARGS]; next unless (ref $box{$bname}->{'handler'} eq "CODE"); my $args = {}; LJ::decode_url_string(\$bargs, $args); my $box = $box{$bname}; $box->{'key'} = $bname; # so we don't have to set it explicitly $box->{'args'} = $args; $box->{'loc'} = $loc; $box->{'pos'} = "$pbox->[$BOX_POS]"; $box->{'uniq'} = "$loc$pbox->[$BOX_POS]"; $box{$bname}->{'handler'}->($remote, $opts, $box); } if ($opts->{'onload'}) { ${$opts->{'bodyopts'}} .= "onLoad=\"" . join('', keys %{$opts->{'onload'}}) . "\""; } } sub box_start { my ($b, $box, $opts) = @_; my $title = $opts->{'title'} || $box->{'name'}; my $mapname = $box->{'uniq'}; my $align = $opts->{'align'} || "left"; my $t = join("-", $box->{'key'}, $box->{'loc'}, $box->{'pos'}); $$b .= "\n"; $$b .= "Down\n"; $$b .= "Up\n"; $$b .= "\"Add/Modify\"\n"; $$b .= "Kill\n"; $$b .= "\n"; if ($box->{'pos'} > 1) { $$b .= "

"; } $$b .= ""; $$b .= "\n"; if ($box->{'loc'} eq "main") { $$b .="
"; $$b .= ""; $$b .= " "; if ($opts->{'url'}) { $$b .= "{'url'}\">"; } $$b .= $title; if ($opts->{'url'}) { $$b .= ""; } $$b .= "
\n"; } else { $$b .= "
"; } } sub box_end { my ($b, $box) = @_; unless ($box->{'loc'} eq "main") { $$b .= "
\n"; $$b .= "\n"; } } # Load site-specific boxes if (-e "$LJ::HOME/cgi-bin/portal-local.pl") { require "$LJ::HOME/cgi-bin/portal-local.pl"; } ############################################################################ $box{'login'} = { 'name' => '', 'small' => 1, 'large' => 0, 'handler' => sub { my ($remote, $opts, $box) = @_; my $b = $opts->{'body'}; box_start($b, $box, { 'title' => "Login", 'align' => "center", 'url' => '/login.bml', }); my $chal = LJ::challenge_generate(300); # 5 minute auth token $$b .= "

"; $$b .= ""; $$b .= "
"; $$b .= "Username:

"; $$b .= "Password:

"; $$b .= " Remember me"; $$b .= ""; $$b .= ""; $$b .= ""; $$b .= "
"; $$b .= < LOGIN $$b .= "
"; box_end($b, $box); $$b .= "
\n"; }, }; ############################################################################ ############################################################################ $box{'stats'} = { 'name' => '', 'small' => 1, 'large' => 0, 'handler' => sub { my ($remote, $opts, $box) = @_; my $dbr = LJ::get_db_reader(); my $b = $opts->{'body'}; my $sth; my @stats; my ($k, $v); box_start($b, $box, { 'title' => BML::ml('portal.stats.portaltitle'), 'url' => '/stats.bml' }); my %stat; $sth = $dbr->prepare("SELECT statkey, statval FROM stats WHERE statcat='statbox'"); $sth->execute; while (my ($k, $v) = $sth->fetchrow_array) { $stat{$k} = $v; } push @stats, BML::ml('portal.stats.totalusers'), $stat{'totusers'}; push @stats, BML::ml('portal.stats.journalentyest'), $stat{'postyester'}; $$b .= ""; while (@stats) { $k = shift @stats; $v = shift @stats; $$b .= ""; $$b .= ""; } $$b .= "
$k
$v
"; box_end($b, $box); }, }; ############################################################################ $box{'bdays'} = { 'name' => '', 'small' => 1, 'large' => 0, 'opts' => [ { 'key' => 'count', 'name' => '', 'des' => '', 'type' => 'text', 'maxlength' => 3, 'size' => 3, 'default' => 5 }, ], 'handler' => sub { my ($remote, $opts, $box) = @_; my $dbr = LJ::get_db_reader(); my $bd = $opts->{'body'}; my $sth; box_start($bd, $box, { 'title' => BML::ml('portal.bdays.portaltitle'), 'url' => '/birthdays.bml' }); # TAG:FR:portal:get_bdays $sth = $dbr->prepare("SELECT u.user, MONTH(bdate) AS 'month', DAYOFMONTH(bdate) AS 'day' FROM friends f, user u WHERE f.userid=$remote->{'userid'} AND f.friendid=u.userid AND u.journaltype='P' AND u.statusvis='V' AND u.allow_infoshow='Y' AND MONTH(bdate) != 0 AND DAYOFMONTH(bdate) != 0"); $sth->execute; # what day is it now? server time... suck, yeah. my @time = localtime(); my ($mnow, $dnow) = ($time[4]+1, $time[3]); my @bdays; while (my ($user, $m, $d) = $sth->fetchrow_array) { my $ref = [ $user, $m, $d ]; if ($m < $mnow || ($m == $mnow && $d < ($dnow))) { # birthday passed this year already $ref->[3] = 1; } push @bdays, $ref; } # sort birthdays that have passed this year after ones that haven't, # otherwise sort by month, otherwise by day. @bdays = sort { # passed sort ($a->[3] <=> $b->[3]) || # month sort ($a->[1] <=> $b->[1]) || # day sort ($a->[2] <=> $b->[2]) } @bdays; # cut the list down my $show = ($box->{'args'}->{'count'} + 0) || 10; if ($show > 100) { $show = 100; } if (@bdays > $show) { @bdays = @bdays[0..$show-1]; } $$bd .= ""; my $add_ord = BML::get_language() =~ /^en/i; foreach my $bi (@bdays) { my $mon = BML::ml( LJ::Lang::month_short_langcode($bi->[1]) ); my $day = $bi->[2]; $day .= LJ::Lang::day_ord($bi->[2]) if $add_ord; $$bd .= ""; $$bd .= ""; } $$bd .= "
" . LJ::ljuser($bi->[0]) . "$mon $day
"; box_end($bd, $box); }, }; ############################################################################ $box{'lastnview'} = { 'name' => '', 'small' => 1, 'large' => 1, 'opts' => [ { 'key' => 'journal', 'name' => '', 'des' => '', 'type' => 'text', 'maxlength' => 15, 'size' => 15, 'default' => '' }, { 'key' => 'items', 'name' => '', 'des' => '', 'type' => 'text', 'maxlength' => 2, 'size' => 2, 'default' => 1 }, { 'key' => 'showtext', 'name' => '', 'des' => '', 'type' => 'check', 'value' => 1, 'default' => 0 }, ], 'handler' => sub { my ($remote, $opts, $box) = @_; my $bd = $opts->{'body'}; my $sth; my $user = LJ::canonical_username($box->{'args'}->{'journal'}); my $items = $box->{'args'}->{'items'}+0 || 1; if ($items > 50) { $items = 50; } unless ($user) { box_start($bd, $box,{'title' => BML::ml('portal.recent.portaltitle') ,}); $$bd .= BML::ml('portal.recent.error.notsetup'); box_end($bd, $box); return; } my $u = LJ::load_user($user); my $dbcr = LJ::get_cluster_reader($u); box_start($bd, $box, { 'title' => "$u->{'name'}", 'url' => "$LJ::SITEROOT/users/$user" }); unless ($u->{'statusvis'} eq "V") { $$bd .= BML::ml('portal.recent.error.userstatus'); box_end($bd, $box); return; } my @itemids; my @items = LJ::get_recent_items({ 'clustersource' => 'slave', 'clusterid' => $u->{'clusterid'}, 'remote' => $remote, 'userid' => $u->{'userid'}, 'skip' => 0, 'itemshow' => $items, 'itemids' => \@itemids, 'order' => ($u->{'journaltype'} eq "C") ? "logtime" : "", }); unless(@itemids) { $$bd .= BML::ml('portal.recent.error.noentries'); box_end($bd, $box); return; } my %logprops = (); my $text = LJ::get_logtext2($u, @itemids); my %posteru = (); # map posterids to u objects LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @items], [$u]); # Loads the log table into cache, in the unlikely event that it is not already in cache LJ::load_log_props2($dbcr, $u->{'userid'}, \@itemids, \%logprops); foreach my $i (@items) { next if $posteru{$i->{'posterid'}}->{'statusvis'} eq 'S'; my $itemid = $i->{'itemid'}; my $event = $text->{$itemid}->[1]; my $subject = $text->{$itemid}->[0]; LJ::CleanHTML::clean_subject(\$subject) if ($subject); $subject ||= "(no subject)"; LJ::CleanHTML::clean_event(\$event, { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'} }) if ($event); my $linkurl = "(Link)"; if ($box->{'args'}->{'showtext'}) { $$bd .= "$subject $linkurl
"; $$bd .= "$event
"; } else { $$bd .= "$subject $linkurl
"; } } box_end($bd, $box); }, }; ############################################################################ $box{'update'} = { 'name' => '', 'small' => 0, 'large' => 1, 'opts' => [ { 'key' => 'mode', 'name' => '', 'type' => 'select', 'des' => '', 'values' => [ "", '', "full", '' ], 'default' => "" }, ], 'handler' => sub { my ($remote, $opts, $box) = @_; my $bd = $opts->{'body'}; my $h = $opts->{'head'}; $opts->{'onload'}->{"settime(document.updateForm$box->{'uniq'});"} = 1; box_start($bd, $box, {'title' => BML::ml('portal.update.portalname'), 'url' => "$LJ::SITEROOT/update.bml", }); my $mode = $opts->{'form'}->{'mode'} || $box->{'args'}->{'mode'}; my $chal = LJ::challenge_generate(300); # 5 minute auth token $$bd .= "
"; $$bd .= ""; $$bd .= ""; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year+=1900; $mon=sprintf("%02d", $mon+1); $mday=sprintf("%02d", $mday); $min=sprintf("%02d", $min); $$bd .= ""; if ($remote) { $$bd .= "\n"; } else { $$bd .= ""; } $$bd .= "
Logged in user: $remote->{'user'} (other user?)
User: "; $$bd .= "Password: "; $$bd .= "
"; $$bd .= "\n"; $$bd .= ""; $$bd .= "
Date: yyyy-mm-ddLocal time: hh:mm (24 hour time)
-"; $$bd .= "-"; $$bd .= "   :"; $$bd .= "
\n"; $$bd .= ""; $$bd .= ""; if ($mode eq "full") { my %res; if (! $opts->{'form'}->{'altlogin'} && $remote) { LJ::do_request({ "mode" => "login", "ver" => $LJ::PROTOCOL_VER, "user" => $remote->{'user'}, "getpickws" => 1, }, \%res, { "noauth" => 1, "userid" => $remote->{'userid'} }); } $$bd .= ""; } else { $$bd .= "\n"; } $$bd .= "
Subject: (optional)
"; $$bd .= "{'form'}->{'subject'}) . "\">
"; $$bd .= "Event:
"; $$bd .= ""; $$bd .= "
<BR>) de?>
"; $$bd .= " "; $$bd .= "
"; $$bd .= < UPDATE $$bd .= "
"; if ($res{'access_count'}) { $$bd .= "

Journal to post in: "; my @access; for (my $i=1; $i<=$res{'access_count'}; $i++) { push @access, $res{"access_$i"}; } $$bd .= LJ::html_select({ 'name' => 'usejournal', 'selected' => $opts->{'form'}->{'usejournal'}, }, "", "($remote->{'user'}) -- default", map { $_, $_ } @access); } $$bd .= "

Security Level: "; $$bd .= LJ::html_select({ 'name' => 'security', 'selected' => $opts->{'form'}->{'security'}, }, "public", "Public", "private", "Private", "friends", "Friends"); $$bd .= LJ::help_icon("security", " "); my $checked; $checked = $opts->{'form'}->{'prop_opt_preformatted'} ? "CHECKED" : ""; $$bd .= "

Don't auto-format:"; $$bd .= LJ::help_icon("noautoformat", " "); $$bd .= "   "; $checked = $opts->{'form'}->{'prop_opt_nocomments'} ? "CHECKED" : ""; $$bd .= "Disallow Comments:"; $checked = $opts->{'form'}->{'prop_opt_backdated'} ? "CHECKED" : ""; $$bd .= "

Backdate Entry: (will only show on calendar)"; if ($res{'pickw_count'}) { $$bd .= "

Picture to use: "; my @pics; for (my $i=1; $i<=$res{'pickw_count'}; $i++) { push @pics, $res{"pickw_$i"}; } @pics = sort { lc($a) cmp lc($b) } @pics; $$bd .= LJ::html_select({'name' => 'prop_picture_keyword', 'selected' => $opts->{'form'}->{'prop_picture_keyword'}, }, ("", "(default)", map { ($_, $_) } @pics)); $$bd .= LJ::help_icon("userpics", " "); } else { $$bd .= "

$res{'errmsg'}"; } $$bd .= "

Current Mood:"; my @sel; my $moods = LJ::get_moods(); foreach my $moodid (sort { $moods->{$a}->{'name'} cmp $moods->{$b}->{'name'} } keys %$moods) { push @sel, $moodid, $moods->{$moodid}->{'name'}; } $$bd .= LJ::html_select({'name' => 'prop_current_moodid', 'selected' => $opts->{'form'}->{'prop_current_moodid'}, }, ("", "None, or other:", @sel)); $$bd .= "Other: {'form'}->{'prop_current_mood'}) . "\">"; $$bd .= "

Current Music: {'form'}->{'prop_current_music'}) . "\">"; $$bd .= '

Tags: '; $$bd .= LJ::html_text( { 'name' => 'prop_taglist', 'size' => '35', 'maxlength' => '255', } ); $$bd .= "

go here. de?>
"; $$h .= <<'JAVASCRIPT_STUFF'; JAVASCRIPT_STUFF box_end($bd, $box); }, }; #################################### ## TODO: let user specify number of random people, and have them ## go horizontally or vertically. $box{'randuser'} = { 'name' => '', 'small' => 1, 'large' => 1, 'opts' => [ { 'key' => 'hidepic', 'name' => '', 'type' => 'check', 'des' => '', 'default' => 0 }, { 'key' => 'hidename', 'name' => '', 'type' => 'check', 'des' => '', 'default' => 0 }, { 'key' => 'count', 'name' => '', 'des' => "", 'type' => 'text', 'maxlength' => 2, 'size' => 2, 'default' => 1 }, ], 'handler' => sub { my ($remote, $opts, $box) = @_; my $dbr = LJ::get_db_reader(); my $b = $opts->{'body'}; my $h = $opts->{'head'}; my $size = get_box_size($box->{'loc'}); my $count = int($box->{'args'}->{'count'}); if ($count < 1) { $count = 1; } if ($size eq "small" && $count > 5) { $count = 5; } if ($size eq "large" && $count > 10) { $count = 10; } my $max = $dbr->selectrow_array("SELECT statval FROM stats WHERE statcat='userinfo' AND statkey='randomcount'"); $count = $max if ($count > $max); my %ruserid; while (keys %ruserid < $count) { $ruserid{int(rand($max))+1} = 1; } unless ($count) { box_start($b, $box, {'title' => BML::ml('portal.randuser.portaltitle'), 'align' => "center", }); $$b .= BML::ml('portal.randuser.error.tableempty'); box_end($b, $box); return; } box_start($b, $box, { 'title' => (keys %ruserid > 1 ? BML::ml('portal.randuser.portaltitleplural') : BML::ml('portal.randuser.portaltitle')), 'align' => "center", }); my @ruser; my $sth = $dbr->prepare(qq{ SELECT userid, user, name, defaultpicid FROM user WHERE userid IN } . "(" . join(",", keys %ruserid) . ")"); $sth->execute; push @ruser, $_ while $_ = $sth->fetchrow_hashref; my %pic; unless ($box->{'args'}->{'hidepic'}) { LJ::load_userpics(\%pic, [ map { [ $_, $_->{'defaultpicid'} ] } @ruser ]); } if ($size eq "large") { $$b .= ""; } my $rct = 1; foreach my $r (@ruser) { if ($size eq "large") { $$b .= ""; } $rct++; } if ($size eq "large") { $$b .= "
"; } elsif ($size eq "small" && $rct > 1) { $$b .= "

"; } my $picid = $r->{'defaultpicid'}; if ($picid && ! $box->{'args'}->{'hidepic'}) { $$b .= "{'userid'}\" width=$pic{$picid}->{'width'} height=$pic{$picid}->{'height'}>
"; } $$b .= "{'user'} ljuser?>"; unless ($box->{'args'}->{'hidename'}) { $$b .= "
" . LJ::ehtml($r->{'name'}); } if ($size eq "large") { $$b .= "

"; } box_end($b, $box); } }; $box{'popfaq'} = { 'name' => '', 'small' => 1, 'large' => 0, 'handler' => sub { my ($remote, $opts, $box) = @_; my $b = $opts->{'body'}; box_start($b, $box, { 'title' => BML::ml('portal.popfaq.portaltitle'), 'align' => "left", 'url' => '/support/faqpop.bml', }); my $dbr = LJ::get_db_reader(); my $sth = $dbr->prepare("SELECT f.faqid, f.question, s.statval AS 'uses' ". "FROM faq f, stats s WHERE f.faqcat<>'int-abuse' AND s.statcat='popfaq' ". "AND s.statkey=f.faqid ORDER BY s.statval DESC LIMIT 10"); $sth->execute; $$b .= "\n"; box_end($b, $box); }, }; ############################################################################ $box{'memories'} = { 'name' => '', 'small' => 1, 'large' => 0, 'handler' => sub { my ($remote, $opts, $box) = @_; my $dbr = LJ::get_db_reader(); my $b = $opts->{'body'}; box_start($b, $box, { 'title' => BML::ml('portal.memories.portaltitle'), 'url' => '/tools/memories.bml', }); my $userid = $remote->{'userid'}; my $kws = LJ::Memories::get_keywords($remote); my $kwcs = LJ::Memories::get_keyword_counts($remote); my $rows = 0; foreach my $id (sort { $kwcs->{$a} <=> $kwcs->{$b} } keys %{$kwcs || {}}) { $$b .= ""; } box_end($b, $box); } }; 1;