Request # head<= <=head bodyopts=>onLoad="check_replytype();updateFaqLink();" body<= '; $sort = 'ASC'; } my $spcatand = ''; if ($sp && ($find eq 'cnext' || $find eq 'cprev')) { my $spcatid = $sp->{_cat}->{'spcatid'} + 0; $spcatand = "AND spcatid=$spcatid"; } else { my @filter_cats = LJ::Support::filter_cats($remote, $cats); return "" unless @filter_cats; my $cats_in = join(",", map { $_->{'spcatid'} } @filter_cats); $spcatand = "AND spcatid IN ($cats_in)"; } my $clause = ""; $clause = "AND spid$op$spid" unless ($find eq 'first' || $find eq 'last'); my $dbr = LJ::get_db_reader(); my ($foundspid) = $dbr->selectrow_array("SELECT spid FROM support WHERE state='open' $spcatand $clause ". "ORDER BY spid $sort LIMIT 1"); if ($foundspid) { return BML::redirect("see_request.bml?id=$foundspid"); } else { my $goback = "Request #$spid p?>" if $sp; my $what = $find eq 'next' || $find eq 'cnext' ? 'next' : 'previous'; my $cat = "in the same category" if $find eq 'cnext' || $find eq 'cprev'; return "$goback"; } } unless ($sp) { return ""; } my $sth; my $auth = $FORM{'auth'}; my $email = $sp->{'reqemail'}; my $u = {}; my $clusterdown = 0; if ($sp->{'reqtype'} eq "user") { $u = LJ::load_userid($sp->{'requserid'}); # now do a check for a down cluster? my $dbr = LJ::get_cluster_reader($u); $clusterdown = 1 unless $dbr; $email = $u->{'email'}; LJ::load_user_props($u, "s1_lastn_style", "s1_calendar_style", "s1_day_style", "s1_friends_style", "stylesys", "s2_style", ) unless $clusterdown; } my $winner; # who closed it? if ($sp->{'state'} eq "closed") { my $dbr = LJ::get_db_reader(); $sth = $dbr->prepare("SELECT u.user, sp.points FROM useridmap u, supportpoints sp ". "WHERE u.userid=sp.userid AND sp.spid=?"); $sth->execute($spid); $winner = $sth->fetchrow_hashref; } # load category this request is in my $problemarea = $sp->{_cat}->{'catname'}; my $catkey = $sp->{_cat}->{'catkey'}; unless (LJ::Support::can_read($sp, $remote, $auth)) { return ""; } # helper variables for commonly called methods my $owner_mode = LJ::Support::can_close($sp, $remote, $auth) ? 1 : 0; my $helper_mode = LJ::Support::can_help($sp, $remote) ? 1 : 0; my $is_poster = LJ::Support::is_poster($sp, $remote, $auth) ? 1 : 0; # fix up the subject if needed eval { if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) { my @subj_data; @subj_data = MIME::Words::decode_mimewords($sp->{'subject'}); if (scalar(@subj_data)) { if (!$1) { $sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]}); } else { $sp->{'subject'} = $subj_data[0][0]; } } } }; ### request info table my $ret = ""; $ret .= "\n"; $ret .= "\n"; # uniq if (LJ::check_priv($remote, 'sysban', 'uniq') || LJ::check_priv($remote, 'sysban', '*')) { my $uniq = $props->{'uniq'} || "none"; $ret .= "\n"; } # account type $ret .= "\n"; $ret .= "\n"; $ret .= "\n"; my $timecreate = LJ::time_to_http($sp->{'timecreate'}); my $age = LJ::ago_text(time() - $sp->{'timecreate'}); $ret .= "\n"; my $state = $sp->{'state'}; if ($state eq "open") { # check if it's still open or needing help or what if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) { # open, answered $state = "answered (awaiting close)"; } elsif ($sp->{'timelasthelp'} && $sp->{'timetouched'} > $sp->{'timelasthelp'}+5) { # open, still needs help $state = "answered (still needs help)"; } else { # default $state = "open"; } } if ($state eq "closed" && $winner && LJ::Support::can_see_helper($sp, $remote)) { my $s = $winner->{'points'} > 1 ? "s" : ""; my $wuser = $winner->{'user'}; $state .= " ($winner->{'points'} point$s to "; $state .= LJ::ljuser($wuser, { 'full' => 1 }) . ")"; } $ret .= "\n"; $ret .= "\n"; $ret .= "
From:"; if ($u->{'defaultpicid'} && $u->{'statusvis'} ne 'S') { my %pic; my $picid = $u->{'defaultpicid'}; LJ::load_userpics(\%pic, [ $u, $picid ]); $ret .= ""; $ret .= "$u->{"; $ret .= ""; } # show requester name + email { my $visemail = $email; if ($sp->{_cat}->{'public_read'}) { $visemail =~ s/^.+\@/********\@/; } my $ename = $sp->{'reqtype'} eq 'user' ? LJ::ljuser($u) : LJ::ehtml($sp->{reqname}); # we show links to the history page if the user is a helper in this category or if it's a # private category and the person has supporthelp somewhere (which is the general rule of # thumb to use the history viewer) my $show_history = !$sp->{_cat}->{public_read} && LJ::check_priv($remote, 'supporthelp'); if ($helper_mode || $show_history) { $ret .= $sp->{reqtype} eq 'user' ? "$ename {user}\">$u->{name}" : "$ename"; $ret .= $owner_mode || $show_history ? " ($visemail)" : " ($visemail)"; } else { # default view $ret .= "$ename ($visemail)"; } } $ret .= "
Uniq:$uniq
Account type:"; $ret .= LJ::name_caps($u->{'caps'}) || "Unknown"; $ret .= "
$LJ::SITENAMESHORT:"; if ($clusterdown) { $ret .= "" . "(unable to connect to cluster, some data temporarily unavailable)
"; } # check isu because requests don't always come from users and sometimes we # fake the user hash if (LJ::isu($u) && $u->readonly) { $ret .= "" . "(this user is currently in read-only mode)
"; } if ($u->{'userid'}) { $ret .= "username: {'user'} ljuserf?>"; $ret .= "
style: "; if ($u->{'stylesys'} == 2) { $ret .= "(S2) "; if ($u->{'s2_style'}) { my $s2style = LJ::S2::load_style($u->{'s2_style'}); my $pub = LJ::S2::get_public_layers(); # cached foreach my $lay (sort { $a cmp $b } keys %{$s2style->{'layer'}}) { my $lid = $s2style->{'layer'}->{$lay}; $ret .= "$lay: "; $ret .= (defined $pub->{$lid} ? 'public' : 'user') . ", "; } } else { $ret .= "none"; } } else { $ret .= "(S1) "; foreach my $view (@LJ::views) { my $styid = $u->{"s1_${view}_style"}; my $viewuri = $view eq "lastn" ? "/users/$u->{'user'}/" : "/users/$u->{'user'}/$view"; if ($view eq "day") { my (undef,undef,undef,$dday,$dmon,$dyear) = localtime(time); $dyear+=1900; $dmon++; $dmon = $dmon <= 9 ? "0$dmon" : $dmon; $dday = $dday <= 9 ? "0$dday" : $dday; $viewuri = "/users/$u->{'user'}/$dyear/$dmon/$dday/"; } $ret .= "$view: $styid "; } if ($u->{'useoverrides'} eq 'Y') { $ret .= "
overrides: view "; } } # if the user has siteadmin:users or siteadmin:* show them link to resend validation email? my $extraval = sub { return '' unless LJ::check_priv($remote, 'siteadmin', 'users') || LJ::check_priv($remote, 'siteadmin', '*'); return " (resend validation email)"; }; $ret .= "
email validated? "; if ($u->{'status'} eq "A") { $ret .= "yes"; } if ($u->{'status'} eq "N") { $ret .= "no" . $extraval->(); } if ($u->{'status'} eq "T") { $ret .= "transitioning (used to be validated, but changed email addresses and hasn't reconfirmed)" . $extraval->(); } if ($u->{clusterid}) { $ret .= "
cluster: " . LJ::get_cluster_description($u->{clusterid}, 1); } $ret .= "
data version: $u->{dversion}"; $ret .= "
underage? "; if ($clusterdown) { $ret .= "cluster unavailable"; } else { if ($u->underage) { $ret .= "yes because of "; $ret .= "birthday" if $u->underage_status eq 'Y'; $ret .= "unique cookie" if $u->underage_status eq 'O'; $ret .= "manual set" if $u->underage_status eq 'M'; $ret .= ""; } else { $ret .= "no"; if ($u->underage_status) { $ret .= "; was by "; $ret .= "birthday" if $u->underage_status eq 'Y'; $ret .= "unique cookie" if $u->underage_status eq 'O'; $ret .= "manual set" if $u->underage_status eq 'M'; } $ret .= ""; } } if (LJ::check_priv($remote, 'historyview')) { $ret .= "
view: "; $ret .= "statushistory"; } } else { $ret .= "not a user"; } $ret .= "
Support category:"; if (LJ::Support::can_read_cat($sp->{_cat}, $remote)) { $ret .= "$problemarea"; $ret .= " [previous|"; $ret .= "next]"; } else { $ret .= $problemarea; } $ret .= "
Time posted:$timecreate ($age)
Status:$state"; if ($owner_mode) { $ret .= $sp->{'state'} eq "open" ? ", {'authcode'}'>close without credit" : ""; if ($sp->{state} eq 'closed') { my $permastatus = LJ::Support::is_locked($sp); $ret .= $sp->{'state'} eq "closed" && !$permastatus ? ", {'authcode'}'>reopen this request" : ""; if (LJ::Support::can_lock($sp, $remote)) { $ret .= $permastatus ? ", unlock request" : ", lock request"; } } } $ret .= "
Summary:" . LJ::ehtml($sp->{'subject'}) . "
\n"; ### end request info table LJ::run_hooks("support_see_request_html", { 'u' => $u, 'email' => $email, 'sp' => $sp, 'retref' => \$ret, 'remote' => $remote, }); # put in a "this is private!" box if this is a private request and the user viewing # this page is the person who opened the request if (!$sp->{_cat}->{public_read} && $is_poster) { $ret .= "
" . "This is a private request. It is not publicly visible.
"; } my %userpics; # id -> {..} my @screened; ### reply loop my $dbr = LJ::get_db_reader(); $sth = $dbr->prepare("SELECT splid, timelogged, UNIX_TIMESTAMP()-timelogged AS 'age', type, faqid, userid, message " . "FROM supportlog WHERE spid=? ORDER BY timelogged"); $sth->execute($spid); while (my $le = $sth->fetchrow_hashref) { next if ($le->{'type'} eq "internal" && ! (LJ::Support::can_read_internal($sp, $remote) || ($remote && $remote->{'userid'} == $le->{'userid'} ))); next if ($le->{'type'} eq "screened" && ! (LJ::Support::can_read_screened($sp, $remote) || ($remote && $remote->{'userid'} == $le->{'userid'} ))); if ($le->{'type'} eq "screened") { push @screened, $le; } my $message = $le->{'message'}; my %url; my $urlN = 0; $message = LJ::ehtml($message); $message =~ s/^\s+//; $message =~ s/\s+$//; $message =~ s/\n( +)/"\n" . "  "x length($1)/eg; $message =~ s/\n/
\n/g; $message = LJ::auto_linkify($message); # special case: original request if ($le->{'type'} eq "req") { # insert support diagnostics from props $message .= "Diagnostics: $props->{useragent}" if $props->{useragent}; $ret .= "
\n"; $ret .= "Original Request:
\n"; $ret .= "
\n$message\n
"; next; } # reply header my $header = ""; if ($le->{'userid'} && LJ::Support::can_see_helper($sp, $remote)) { my $up = LJ::load_userid($le->{'userid'}); my $picid = $up->{'defaultpicid'}; $userpics{$picid} or LJ::load_userpics(\%userpics, [[ $up, $picid ]]); $header = ""; if ($picid && $up->{'statusvis'} ne 'S') { $header .= ""; } $header .= "
$up->{" . LJ::ljuser($up->{'user'}, { 'full' => 1 }); if ($up->{'statusvis'} ne 'S') { $header .= " - " . LJ::ehtml($up->{'name'}); } $header .= "
\n" } my $what = "Answer"; if ($le->{'type'} eq "internal") { $what = "Internal Comment"; } elsif ($le->{'type'} eq "comment") { $what = "Comment"; } elsif ($le->{'type'} eq "screened") { $what = "Screened Response"; } $header .= "$what (\#$le->{'splid'})
"; my $timehelped = LJ::time_to_http($le->{'timelogged'}); my $age = LJ::ago_text($le->{'age'}); $header .= "Posted: $timehelped ($age)"; if ($owner_mode && $sp->{'state'} eq "open" && $le->{'type'} eq "answer") { $header .= ", {'authcode'};$le->{'splid'}'>credit fix here"; } my $bordercolor = "#000000"; if ($le->{'type'} eq "internal") { $bordercolor = "#ff0000"; } if ($le->{'type'} eq "answer") { $bordercolor = "#00c000"; } if ($le->{'type'} eq "screened") { $bordercolor = "#afaf00"; } # reply $ret .= "$header
\n"; $ret .= "\n"; $ret .= "
\n"; if ($le->{'faqid'}) { # faq question my $dbr = LJ::get_db_reader(); my $sth = $dbr->prepare("SELECT question FROM faq WHERE faqid=?"); $sth->execute($le->{'faqid'}); my $faqname = $sth->fetchrow_array; $ret .= "
\n"; # whitespace between these two DIVs is necessary for proper # rendering in IE 5 for Mac OS < X $ret .= "
"; $ret .= "FAQ Reference:
$faqname
\n"; } $ret .= "

$message

\n"; $ret .= "
\n"; } ### end reply loop # return if support item is closed if ($sp->{'state'} eq "closed") { return $ret; } # underage users can't interact with this return $ret if $remote && $remote->underage; $ret .= "

Post a comment or solution:

\n"; unless ($remote || $is_poster) { $ret .= "You must login to help people out.\n"; return $ret; } unless (LJ::Support::can_append($sp, $remote, $auth)) { $ret .= "Sorry, you do not have access to answer people's support requests in this category.\n"; return $ret; } my @ans_type = LJ::Support::get_answer_types($sp, $remote, $auth); my %ans_type = @ans_type; if ($ans_type{'answer'} || $ans_type{'screened'}) { $ret .= "Important Notes:"; $ret .= "Thanks! standout?>\n"; } # append_request form $ret .= "
\n"; # hidden values $ret .= LJ::html_hidden('spid', $spid, 'auth', $auth) . "\n"; # form $ret .= "\n"; $ret .= "\n"; if ($ans_type{'answer'} || $ans_type{'screened'}) { my $dbr = LJ::get_db_reader(); # FAQ reference $ret .= "\n"; } # answer type { $ret .= "\n"; } # helpers can do actions: if (LJ::Support::can_perform_actions($sp, $remote) && ! $is_poster) { $ret .= "\n"; if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) { $ret .= "\n"; } else { $ret .= "\n"; } if (LJ::Support::can_change_summary($sp, $remote)) { $ret .= "\n"; $ret .= "\n"; } } # Prefill an e-mail validation nag, if needed. my $validationnag; if (!(LJ::isu($u) && ($u->underage && $u->{'status'} eq 'T')) && ($u->{'status'} eq "N" || $u->{'status'} eq "T") && ! $is_poster) { my $reminder = LJ::load_include('validationreminder'); $validationnag .= "\n\n$reminder" if $reminder; } # add in canned answers if there are any for this category and the user can use them if ($helper_mode && ! $is_poster) { my $rows = $dbr->selectall_arrayref('SELECT subject, body FROM support_answers WHERE spcatid = ? ORDER BY subject', undef, $sp->{_cat}->{spcatid}); if ($rows && @$rows) { $ret .= ""; } } # textarea for their message body $ret .= "
From:"; if ($remote && $remote->{'userid'}) { $ret .= "{'user'} ljuser?>"; } else { $ret .= "(not logged in)"; } $ret .= "
Reference FAQ:\n"; my %faqcat; my %faqq; $sth = $dbr->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat WHERE faqcat<>'int-abuse'"); $sth->execute; while ($_ = $sth->fetchrow_hashref) { $faqcat{$_->{'faqcat'}} = $_; } $sth = $dbr->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime FROM faq WHERE faqcat<>'int-abuse'"); $sth->execute; while ($_ = $sth->fetchrow_hashref) { $faqq{$_->{'faqid'}} = $_; } my @faqlist = ('0', "(don't reference FAQ)"); foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> $faqcat{$b}->{'catorder'} } keys %faqcat) { push @faqlist, ('0', "[ $faqcat{$faqcat}->{'faqcatname'} ]"); foreach my $faqid (sort { $faqq{$a}->{'sortorder'} <=> $faqq{$b}->{'sortorder'} } grep { $faqq{$_}->{'faqcat'} eq $faqcat } keys %faqq) { next unless ($faqq{$faqid}->{'question'}); my $q = "... $faqq{$faqid}->{'question'}"; $q =~ s/^\s+//; $q =~ s/\s+$//; $q =~ s/\n/ /g; if (length($q) > 50) { $q = substr($q, 0, 50) . "..."; } push @faqlist, ($faqid, $q); } } $ret .= LJ::html_select({ 'name' => 'faqid', 'onchange' => 'updateFaqLink()' }, @faqlist) . "\n"; $ret .= qq(); $ret .= "
Reply Type:"; # if less than 2, remote is the person filing the request # so all they can do is add more info if (@ans_type > 2) { $ret .= LJ::html_select({ 'name' => 'replytype', 'onchange' => "check_replytype()" }, @ans_type) . "\n"; $ret .= ""; } else { $ret .= LJ::html_hidden('replytype', $ans_type[0]) . "\n"; $ret .= "$ans_type[1]"; } $ret .= "
\n"; $ret .= ""; $ret .= ""; if (@screened && $helper_mode) { $ret .= ""; } $ret .= "
Change Category:
"; $ret .= LJ::html_select({ 'name' => 'changecat' }, ('', $sp->{'_cat'}->{'catname'}), map { $_->{'spcatid'}, "---> $_->{'catname'}" } LJ::Support::sorted_cats($cats)); $ret .= "
Approve Screened Response:
"; $ret .= LJ::html_select({ 'name' => 'approveans' }, ('', ''), map { $_->{'splid'}, "\#$_->{'splid'} (" . LJ::get_username($_->{'userid'}) . ")" } @screened); $ret .= LJ::html_select({ 'name' => 'approveas' }, ("answer" => "as answer", "comment" => "as comment",)); $ret .= "
\n"; $ret .= "
Put in Queue:"; $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'touch' }); $ret .= "\n"; $ret .= "
Take out of Queue:"; $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'untouch' }); $ret .= "\n"; $ret .= "
Change summary:"; $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'changesum' }); $ret .= LJ::html_text({ 'type' => 'text', 'name' => 'summary', 'size' => '50', 'maxlength' => '80', 'value' => $sp->{'subject'} }); $ret .= "
 "; $ret .= "\n"; $ret .= "
Stock answers:\n"; $ret .= "\n"; $ret .= "
Message:"; $ret .= LJ::html_textarea({ 'rows' => '12', 'cols' => '80', 'wrap' => 'virtual', 'id' => 'body', 'name' => 'body', 'value' => $validationnag }) . "
"; $ret .= "URLs are automatically link-ified, so just reference those. de?>
"; $ret .= LJ::html_submit('submitpost', "Post Comment/Solution"); $ret .= "
\n"; $ret .= "
\n"; return $ret; } _code?> previous open request, " . "next open request" } _code?>
Back to the list of open requests.
Back to the support area. <=body page?> link: htdocs/support/faqbrowse.bml, htdocs/styles/browse/styleinfo.bml link: htdocs/support/help.bml, htdocs/support/act.bml, htdocs/login.bml link: htdocs/guide/support.bml, htdocs/support/faq.bml, htdocs/support/index.bml link: htdocs/allpics.bml img: htdocs/userpic post: htdocs/support/append_request.bml _c?>