function selectors() { $sel = array("students" => "All students"); foreach (ContactView::pset_list(true, false) as $pset) { if (Contact::student_can_see_pset($pset)) { if (!$pset->gitless || $pset->partner) { $sel[] = array("optgroup", $pset->title); } if (!$pset->gitless) { $sel[$pset->urlkey . ":workingrepo"] = "{$pset->title}, working repo"; $sel[$pset->urlkey . ":brokenrepo"] = "{$pset->title}, broken repo"; $sel[$pset->urlkey . ":openrepo"] = "{$pset->title}, open repo"; $sel[$pset->urlkey . ":norepo"] = "{$pset->title}, no repo"; } if ($pset->partner) { $sel[$pset->urlkey . ":partner"] = "{$pset->title}, partner"; $sel[$pset->urlkey . ":nopartner"] = "{$pset->title}, no partner"; } } } $sel[] = array("optgroup"); $sel["pc"] = "TFs"; foreach (pcTags() as $t) { if ($t != "pc") { $sel["pc:{$t}"] = "#{$t} TFs"; } } $sel["all"] = "All users"; $usersel = array("all" => "All", "college" => "College", "extension" => "Extension"); return Ht::select("recipients", $sel, $this->type, array("id" => "recipients", "onchange" => "setmailpsel(this)")) . " " . Ht::select("userrecipients", $usersel, $this->usertype, array("id" => "userrecipients")); }
function __construct($contact, $type, $papersel, $newrev_since) { global $Conf, $Now; $this->contact = $contact; assert(!!$contact->isPC); $any_newpcrev = $any_lead = $any_shepherd = 0; if ($contact->is_manager()) { $this->defsel("s", "Contact authors of submitted papers"); $this->defsel("unsub", "Contact authors of unsubmitted papers"); $this->defsel("au", "All contact authors"); // map "somedec:no"/"somedec:yes" to real decisions $result = Dbl::qe("select outcome, count(*) from Paper where timeSubmitted>0 group by outcome"); $dec_pcount = edb_map($result); $dec_tcount = array(0 => 0, 1 => 0, -1 => 0); foreach ($dec_pcount as $dnum => $dcount) { $dec_tcount[$dnum > 0 ? 1 : ($dnum < 0 ? -1 : 0)] += $dcount; } if ($type == "somedec:no" || $type == "somedec:yes") { $dmaxcount = -1; foreach ($dec_pcount as $dnum => $dcount) { if (($type[8] == "n" ? $dnum < 0 : $dnum > 0) && $dcount > $dmaxcount && ($dname = $Conf->decision_name($dnum))) { $type = "dec:{$dname}"; $dmaxcount = $dcount; } } } $by_dec = array(); foreach ($Conf->decision_map() as $dnum => $dname) { $k = "dec:{$dname}"; if ($dnum && (@$dec_pcount[$dnum] > 0 || $type == $k)) { $by_dec[$k] = "Contact authors of " . htmlspecialchars($dname) . " papers"; } } if ($dec_tcount[1] > 0 || $type == "dec:yes") { $by_dec["dec:yes"] = "Contact authors of accept-class papers"; } if ($dec_tcount[-1] > 0 || $type == "dec:no") { $by_dec["dec:no"] = "Contact authors of reject-class papers"; } if ($dec_tcount[0] > 0 || $type == "dec:none") { $by_dec["dec:none"] = "Contact authors of undecided papers"; } if ($type == "dec:any") { $by_dec["dec:any"] = "Contact authors of decided papers"; } if (count($by_dec)) { $this->sel["bydec_group"] = array("optgroup", "Contact authors by decision"); foreach ($by_dec as $k => $v) { $this->defsel($k, $v); } $this->sel["bydec_group_end"] = array("optgroup"); } $this->sel["rev_group"] = array("optgroup", "Reviewers"); $this->defsel("rev", "Reviewers"); $this->defsel("crev", "Reviewers with complete reviews"); $this->defsel("uncrev", "Reviewers with incomplete reviews"); $this->defsel("allcrev", "Reviewers with no incomplete reviews"); $this->defsel("pcrev", "PC reviewers"); $this->defsel("uncpcrev", "PC reviewers with incomplete reviews"); // new assignments query // XXX this exposes information about PC review assignments // for conflicted papers to the chair; not worth worrying about $aq = "select PaperReview.paperId any_newpcrev from PaperReview"; if (!$contact->privChair) { $aq .= " join Paper on (Paper.paperId=PaperReview.paperId and Paper.managerContactId=" . $contact->contactId . ")"; } $aq .= "\n\twhere reviewType>=" . REVIEW_PC . " and reviewSubmitted is null and reviewNeedsSubmit!=0 and timeRequested>timeRequestNotified limit 1"; $bcq_manager = ""; if (!$contact->privChair) { $bcq_manager = " and managerContactId=" . $contact->contactId; } $q = "select any_newpcrev, any_lead, any_shepherd\n\tfrom ({$aq}) a\n\tleft join (select paperId any_lead from Paper where timeSubmitted>0 and leadContactId!=0{$bcq_manager} limit 1) b on (true)\n\tleft join (select paperId any_shepherd from Paper where timeSubmitted>0 and shepherdContactId!=0{$bcq_manager} limit 1) c on (true)"; if ($row = Dbl::fetch_first_row($q)) { list($any_newpcrev, $any_lead, $any_shepherd) = $row; } $this->defsel("newpcrev", "PC reviewers with new review assignments"); $this->defsel("extrev", "External reviewers"); $this->defsel("uncextrev", "External reviewers with incomplete reviews"); $this->sel["rev_group_end"] = array("optgroup"); } $this->defsel_nm("myextrev", "Your requested reviewers"); $this->defsel_nm("uncmyextrev", "Your requested reviewers with incomplete reviews"); $this->sel["pc_group"] = array("optgroup", "Program committee"); if ($contact->is_manager()) { if ($any_lead || $type == "lead") { $this->defsel("lead", "Discussion leads"); } if ($any_shepherd || $type == "shepherd") { $this->defsel("shepherd", "Shepherds"); } } $this->defsel_nm("pc", "Program committee"); foreach (pcTags() as $t) { if ($t != "pc") { $this->defsel_nm("pc:{$t}", "PC members tagged “{$t}”"); } } $this->sel["pc_group_end"] = array("optgroup"); if ($contact->privChair) { $this->defsel("all", "All users"); } if (isset($this->sel[$type])) { $this->type = $type; } else { if ($type == "myuncextrev" && isset($this->sel["uncmyextrev"])) { $this->type = "uncmyextrev"; } else { $this->type = key($this->sel); } } $this->papersel = $papersel; if ($this->type == "newpcrev") { $t = @trim($newrev_since); if (preg_match(',\\A(?:|n/a|[(]?all[)]?|0)\\z,i', $t)) { $this->newrev_since = 0; } else { if (($this->newrev_since = $Conf->parse_time($t)) !== false) { if ($this->newrev_since > $Now) { $Conf->warnMsg("That time is in the future."); } } else { Conf::msg_error("Invalid date."); $this->error = true; } } } }
// HotCRP is Copyright (c) 2006-2016 Eddie Kohler and Regents of the UC // Distributed under an MIT-like license; see LICENSE require_once "src/initweb.php"; require_once "src/contactlist.php"; $getaction = ""; if (isset($_REQUEST["get"])) { $getaction = $_REQUEST["get"]; } else { if (isset($_REQUEST["getgo"]) && isset($_REQUEST["getaction"])) { $getaction = $_REQUEST["getaction"]; } } // list type $tOpt = array(); $tOpt["pc"] = "Program committee"; if ($Me->isPC && count($pctags = pcTags())) { foreach ($pctags as $t) { if ($t != "pc") { $tOpt["#{$t}"] = "#{$t} program committee"; } } } if ($Me->isPC) { $tOpt["admin"] = "System administrators"; } if ($Me->privChair || $Me->isPC && $Conf->timePCViewAllReviews()) { $tOpt["re"] = "All reviewers"; $tOpt["ext"] = "External reviewers"; $tOpt["extsub"] = "External reviewers who completed a review"; } if ($Me->isPC) {
doRadio('a', 'clear', 'Clear all '); doSelect('cleartype', array(REVIEW_PRIMARY => "primary", REVIEW_SECONDARY => "secondary", REVIEW_PC => "optional", "conflict" => "conflict", "lead" => "discussion lead", "shepherd" => "shepherd")); echo " assignments for selected papers and PC members"; echo "<div class='g'></div>", divClass("discorder", "hotradiorelation"); doRadio("a", "discorder", "Create discussion order in tag #"); echo Ht::entry("discordertag", get($Qreq, "discordertag", "discuss"), array("size" => 12, "onfocus" => 'autosub(false,this)')), ", grouping papers with similar PC conflicts</div>"; echo "</div>\n"; // PC echo "<h3>PC members</h3><table><tr><td class=\"nw\">"; doRadio("pctyp", "all", ""); echo "</td><td>", Ht::label("Use entire PC", "pctyp_all"), "</td></tr>\n"; echo "<tr><td class=\"nw\">"; doRadio('pctyp', 'sel', ''); echo "</td><td>", Ht::label("Use selected PC members:", "pctyp_sel"), " (select "; $pctyp_sel = array(array("all", 1, "all"), array("none", 0, "none")); $pctags = pcTags(); if (count($pctags)) { $tagsjson = array(); foreach (pcMembers() as $pc) { $tagsjson[$pc->contactId] = " " . trim(strtolower($pc->viewable_tags($Me))) . " "; } $Conf->footerScript("pc_tags_json=" . json_encode($tagsjson) . ";"); foreach ($pctags as $tagname => $pctag) { if ($tagname !== "pc" && Tagger::strip_nonviewable($tagname, $Me)) { $pctyp_sel[] = array($pctag, "pc_tags_members(\"{$tagname}\")", "#{$pctag}"); } } } $pctyp_sel[] = array("__flip__", -1, "flip"); $sep = ""; foreach ($pctyp_sel as $pctyp) {
private function _search_comment($word, $ctype, &$qt, $quoted) { global $Conf; $m = self::_matchCompar($word, $quoted); if ($qr = self::_tautology($m[1])) { $qt[] = $qr; return; } // canonicalize comment type $ctype = strtolower($ctype); if (str_ends_with($ctype, "resp")) { $ctype .= "onse"; } if (str_ends_with($ctype, "-draft")) { $ctype = "draft" . substr($ctype, 0, strlen($ctype) - 6); } else { if (str_ends_with($ctype, "draft")) { $ctype = "draft" . substr($ctype, 0, strlen($ctype) - 5); } } if (str_starts_with($ctype, "draft-")) { $ctype = "draft" . substr($ctype, 6); } $rt = 0; $round = null; if (str_starts_with($ctype, "draft") && str_ends_with($ctype, "response")) { $rt |= self::F_REQUIREDRAFT | self::F_ALLOWDRAFT; $ctype = substr($ctype, 5); } if ($ctype === "response" || $ctype === "anycmt") { $rt |= self::F_ALLOWRESPONSE; } else { if (str_ends_with($ctype, "response")) { $rname = substr($ctype, 0, strlen($ctype) - 8); $round = $Conf->resp_round_number($rname); if ($round === false) { $this->warn("No such response round “" . htmlspecialchars($ctype) . "”."); $qt[] = new SearchTerm("f"); return; } $rt |= self::F_ALLOWRESPONSE; } } if ($ctype === "cmt" || $ctype === "aucmt" || $ctype === "anycmt") { $rt |= self::F_ALLOWCOMMENT; } if ($ctype === "aucmt") { $rt |= self::F_AUTHORCOMMENT; } if (substr($m[0], 0, 1) === "#") { $rt |= ($this->privChair ? 0 : self::F_NONCONFLICT) | self::F_XVIEW; $tags = $this->_expand_tag(substr($m[0], 1), false); foreach ($tags as $tag) { $this->_search_comment_tag($rt, $tag, $m[1], $round, $qt); } if (!count($tags)) { $qt[] = new SearchTerm("f"); return; } else { if (count($tags) !== 1 || $tags[0] === "none" || $tags[0] === "any" || !pcTags($tags[0])) { return; } } } $contacts = $m[0] === "" ? null : $this->_reviewerMatcher($m[0], $quoted, false); $value = new ContactCountMatcher($m[1], $contacts); $term = new SearchTerm("cmt", $rt | self::F_XVIEW, $value); if ($round !== null) { $term->commentRound = $round; } $qt[] = $term; }
function meaningful_pc_tag() { global $Me; if ($Me->isPC) { foreach (pcTags() as $tag) { if ($tag !== "pc") { return $tag; } } } return false; }
public function compile(FormulaCompiler $state) { $state->datatype |= self::ASUBREV; $state->queryOptions["reviewIdentities"] = true; $flags = 0; $arg = $this->arg; if ($arg[0] === "\"") { $flags |= ContactSearch::F_QUOTED; $arg = str_replace("\"", "", $arg); } if (!($flags & ContactSearch::F_QUOTED) && ($arg[0] === "#" || pcTags($arg)) && $state->contact->can_view_reviewer_tags()) { $cvt = $state->define_gvar('can_view_reviewer_tags', '$contact->can_view_reviewer_tags($prow)'); $tag = $arg[0] === "#" ? substr($arg, 1) : $arg; $e = "({$cvt} ? ReviewerMatchFexpr::check_tagmap(" . $state->_rrow_cid() . ", " . json_encode($tag) . ") : null)"; } else { $flags |= ContactSearch::F_TAG | ContactSearch::F_NOUSER; $cs = new ContactSearch($flags, $arg, $state->contact); if ($cs->ids) { // XXX information leak? $e = "(\$prow->can_view_review_identity_of(" . $state->_rrow_cid() . ", \$contact, \$forceShow) ? array_search(" . $state->_rrow_cid() . ", [" . join(", ", $cs->ids) . "]) !== false : null)"; } else { $e = "null"; } } return $e; }