public function documents(PaperInfo $prow) { assert($this->option->has_document_storage()); if ($this->_documents === null) { $this->_documents = $by_unique_filename = array(); $docclass = null; foreach ($this->values as $docid) { if ($docid > 1 && ($d = $prow->document($this->id, $docid))) { $d->docclass = $docclass = $docclass ?: new HotCRPDocument($this->id); $d->unique_filename = $d->filename; while (get($by_unique_filename, $d->unique_filename)) { if (preg_match('/\\A(.*\\()(\\d+)(\\)(?:\\.\\w+|))\\z/', $d->unique_filename, $m)) { $d->unique_filename = $m[1] . ($m[2] + 1) . $m[3]; } else { if (preg_match('/\\A(.*?)(\\.\\w+|)\\z/', $d->unique_filename, $m) && $m[1] !== "") { $d->unique_filename = $m[1] . " (1)" . $m[2]; } else { $d->unique_filename .= " (1)"; } } } $by_unique_filename[$d->unique_filename] = true; $this->_documents[] = $d; } } } return $this->_documents; }
function run(Contact $user, $qreq, $ssel) { global $Conf; $o = cvtint($qreq->decision); $decision_map = $Conf->decision_map(); if ($o === null || !isset($decision_map[$o])) { return Conf::msg_error("Bad decision value."); } $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection()))); $success = $fails = array(); while ($prow = PaperInfo::fetch($result, $user)) { if ($user->can_set_decision($prow, true)) { $success[] = $prow->paperId; } else { $fails[] = "#" . $prow->paperId; } } if (count($fails)) { Conf::msg_error("You cannot set paper decisions for " . pluralx($fails, "paper") . " " . commajoin($fails) . "."); } if (count($success)) { Dbl::qe("update Paper set outcome={$o} where paperId ?a", $success); $Conf->update_paperacc_setting($o > 0); redirectSelf(array("atab" => "decide", "decision" => $o)); } }
function saveTagIndexes($tag, $filename, &$settings, &$titles, &$linenos, &$errors) { global $Conf, $Me, $Error; $result = $Conf->qe($Conf->paperQuery($Me, array("paperId" => array_keys($settings)))); while ($row = PaperInfo::fetch($result, $Me)) { if ($settings[$row->paperId] !== null && !$Me->can_change_tag($row, $tag, null, 1)) { $errors[$linenos[$row->paperId]] = "You cannot rank paper #{$row->paperId}."; unset($settings[$row->paperId]); } else { if ($titles[$row->paperId] !== "" && strcmp($row->title, $titles[$row->paperId]) != 0 && strcasecmp($row->title, simplify_whitespace($titles[$row->paperId])) != 0) { $errors[$linenos[$row->paperId]] = "Warning: Title doesn’t match"; } } } if (!$tag) { defappend($Error["tags"], "No tag defined"); } else { if (count($settings)) { $x = array("paper,tag,lineno"); foreach ($settings as $pid => $value) { $x[] = "{$pid},{$tag}#" . ($value === null ? "clear" : $value) . "," . $linenos[$pid]; } $assigner = new AssignmentSet($Me); $assigner->parse(join("\n", $x) . "\n", $filename); $assigner->report_errors(); $assigner->execute(); } } $settings = $titles = $linenos = array(); }
function saveAssignments($qreq, $reviewer) { global $Conf, $Me, $Now, $pcm; $reviewer_contact = $pcm[$reviewer]; $round_number = null; if (!count($qreq->assrev)) { return; } $result = Dbl::qe_raw($Conf->paperQuery($Me, array("paperId" => array_keys($qreq->assrev), "reviewer" => $reviewer))); $lastPaperId = -1; $del = $ins = ""; while ($row = PaperInfo::fetch($result, $Me)) { if ($row->paperId == $lastPaperId || !$Me->can_administer($row) || $row->reviewerConflictType >= CONFLICT_AUTHOR || !isset($qreq->assrev[$row->paperId])) { continue; } $lastPaperId = $row->paperId; $type = $qreq->assrev[$row->paperId]; if ($type >= 0 && $row->reviewerConflictType > 0 && $row->reviewerConflictType < CONFLICT_AUTHOR) { $del .= " or paperId={$row->paperId}"; } if ($type < 0 && $row->reviewerConflictType < CONFLICT_CHAIRMARK) { $ins .= ", ({$row->paperId}, {$reviewer}, " . CONFLICT_CHAIRMARK . ")"; } if ($qreq->kind == "a" && $type != $row->reviewerReviewType && ($type <= 0 || $reviewer_contact->can_accept_review_assignment_ignore_conflict($row))) { if ($type > 0 && $round_number === null) { $round_number = $Conf->round_number($qreq->rev_roundtag, true); } $Me->assign_review($row->paperId, $reviewer, $type, array("round_number" => $round_number)); } } if ($ins) { $Conf->qe("insert into PaperConflict (paperId, contactId, conflictType) values " . substr($ins, 2) . " on duplicate key update conflictType=greatest(conflictType,values(conflictType))"); } if ($del) { $Conf->qe("delete from PaperConflict where contactId={$reviewer} and (" . substr($del, 4) . ")"); } $Conf->update_rev_tokens_setting(false); if ($Conf->setting("pcrev_assigntime") == $Now) { $Conf->confirmMsg("Assignments saved! You may want to <a href=\"" . hoturl("mail", "template=newpcrev") . "\">send mail about the new assignments</a>."); } redirectSelf(["kind" => $qreq->kind]); }
function run(Contact $user, $qreq, $ssel) { global $Conf, $Opt; $q = $Conf->paperQuery($user, ["paperId" => $ssel->selection(), "topics" => true, "options" => true]); $result = Dbl::qe_raw($q); $pj = []; $ps = new PaperStatus($user, ["forceShow" => true, "hide_docids" => true]); if ($this->iszip) { $this->zipdoc = new ZipDocument($Opt["downloadPrefix"] . "data.zip"); $ps->add_document_callback([$this, "document_callback"]); } while ($prow = PaperInfo::fetch($result, $user)) { if ($user->can_administer($prow, true)) { $pj[$prow->paperId] = $ps->paper_json($prow); } else { $pj[$prow->paperId] = (object) ["pid" => $prow->paperId, "error" => "You don’t have permission to administer this paper."]; if ($this->iszip) { $this->zipdoc->warnings[] = "#{$prow->paperId}: You don’t have permission to administer this paper."; } } } $pj = array_values($ssel->reorder($pj)); if (count($pj) == 1) { $pj = $pj[0]; $pj_filename = $Opt["downloadPrefix"] . "paper" . $ssel->selection_at(0) . "-data.json"; } else { $pj_filename = $Opt["downloadPrefix"] . "data.json"; } if ($this->iszip) { $this->zipdoc->add(json_encode($pj, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n", $pj_filename); $this->zipdoc->download(); } else { header("Content-Type: application/json"); header("Content-Disposition: attachment; filename=" . mime_quote_string($pj_filename)); echo json_encode($pj, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; } exit; }
function run(Contact $user, $qreq, $ssel) { global $Conf, $Opt; $q = $Conf->paperQuery($user, array("paperId" => $ssel->selection(), "allReviewerPreference" => 1, "allConflictType" => 1, "topics" => 1)); $result = Dbl::qe_raw($q); $texts = array(); $pcm = pcMembers(); $has_conflict = $has_expertise = $has_topic_score = false; while ($prow = PaperInfo::fetch($result, $user)) { if (!$user->can_administer($prow, true)) { continue; } $conflicts = $prow->conflicts(); foreach ($pcm as $cid => $p) { $pref = $prow->reviewer_preference($p); $conf = get($conflicts, $cid); $tv = $prow->topicIds ? $prow->topic_interest_score($p) : 0; if ($pref || $conf || $tv) { $texts[$prow->paperId][] = array("paper" => $prow->paperId, "title" => $prow->title, "first" => $p->firstName, "last" => $p->lastName, "email" => $p->email, "preference" => $pref[0] ?: "", "expertise" => unparse_expertise($pref[1]), "topic_score" => $tv ?: "", "conflict" => $conf ? "conflict" : ""); $has_conflict = $has_conflict || $conf; $has_expertise = $has_expertise || $pref[1] !== null; $has_topic_score = $has_topic_score || $tv; } } } $headers = array("paper", "title", "first", "last", "email", "preference"); if ($has_expertise) { $headers[] = "expertise"; } if ($has_topic_score) { $headers[] = "topic_score"; } if ($has_conflict) { $headers[] = "conflict"; } downloadCSV($ssel->reorder($texts), $headers, "allprefs", ["selection" => true]); }
private static function status_papers($status, $tracker, $acct) { global $Conf; $pids = array_slice($tracker->ids, $tracker->position, 3); $pc_conflicts = $acct->privChair || $acct->tracker_kiosk_state; $col = $j = ""; if ($pc_conflicts) { $col = ", allconfs.conflictIds"; $j = "left join (select paperId, group_concat(contactId) conflictIds from PaperConflict where paperId in (" . join(",", $pids) . ") group by paperId) allconfs on (allconfs.paperId=p.paperId)\n\t\t"; $pcm = pcMembers(); } $result = $Conf->qe("select p.paperId, p.title, p.paperFormat, p.leadContactId, p.managerContactId, r.reviewType, conf.conflictType{$col}\n from Paper p\n left join PaperReview r on (r.paperId=p.paperId and " . ($acct->contactId ? "r.contactId={$acct->contactId}" : "false") . ")\n left join PaperConflict conf on (conf.paperId=p.paperId and " . ($acct->contactId ? "conf.contactId={$acct->contactId}" : "false") . ")\n {$j}where p.paperId in (" . join(",", $pids) . ")"); $papers = array(); while ($row = PaperInfo::fetch($result, $acct)) { $papers[$row->paperId] = $p = (object) array(); if (($acct->privChair || !$row->conflictType || !get($status, "hide_conflicts")) && $acct->tracker_kiosk_state != 1) { $p->pid = (int) $row->paperId; $p->title = $row->title; if ($format = $row->title_format()) { $p->format = $format; } } if ($acct->contactId > 0 && $row->managerContactId == $acct->contactId) { $p->is_manager = true; } if ($row->reviewType) { $p->is_reviewer = true; } if ($row->conflictType) { $p->is_conflict = true; } if ($acct->contactId > 0 && $row->leadContactId == $acct->contactId) { $p->is_lead = true; } if ($pc_conflicts) { $p->pc_conflicts = array(); foreach (explode(",", (string) $row->conflictIds) as $cid) { if ($pc = get($pcm, $cid)) { $p->pc_conflicts[$pc->sort_position] = (object) array("email" => $pc->email, "name" => Text::name_text($pc)); } } ksort($p->pc_conflicts); $p->pc_conflicts = array_values($p->pc_conflicts); } } Dbl::free($result); $status->papers = array(); foreach ($pids as $pid) { $status->papers[] = $papers[$pid]; } }
function crpmerge_database($old_user, $new_user) { global $Conf, $MergeError; // Now, scan through all the tables that possibly // specify a contactID and change it from their 2nd // contactID to their first contactId $oldid = $old_user->contactId; $newid = $new_user->contactId; $Conf->q("lock tables Paper write, ContactInfo write, PaperConflict write, ActionLog write, TopicInterest write, PaperComment write, PaperReview write, PaperReview as B write, PaperReviewPreference write, PaperReviewRefused write, ReviewRequest write, PaperWatch write, ReviewRating write"); crpmergeone("Paper", "leadContactId", $oldid, $newid); crpmergeone("Paper", "shepherdContactId", $oldid, $newid); crpmergeone("Paper", "managerContactId", $oldid, $newid); // paper authorship $result = $Conf->qe("select paperId, authorInformation from Paper where authorInformation like " . Dbl::utf8ci("'%\t" . sqlq_for_like($old_user->email) . "\t%'")); $qs = array(); while ($row = PaperInfo::fetch($result, null)) { foreach ($row->author_list() as $au) { if (strcasecmp($au->email, $old_user->email) == 0) { $au->email = $new_user->email; } } $qs[] = "update Paper set authorInformation='" . sqlq($row->parse_author_list()) . "' where paperId={$row->paperId}"; } foreach ($qs as $q) { $Conf->qe($q); } // ensure uniqueness in PaperConflict $result = $Conf->qe("select paperId, conflictType from PaperConflict where contactId={$oldid}"); $values = ""; while ($row = edb_row($result)) { $values .= ", ({$row['0']}, {$newid}, {$row['1']})"; } if ($values) { $Conf->qe("insert into PaperConflict (paperId, contactId, conflictType) values " . substr($values, 2) . " on duplicate key update conflictType=greatest(conflictType, values(conflictType))"); } $Conf->qe("delete from PaperConflict where contactId={$oldid}"); if (($old_user->roles | $new_user->roles) != $new_user->roles) { $new_user->roles |= $old_user->roles; $Conf->qe("update ContactInfo set roles={$new_user->roles} where contactId={$newid}"); } crpmergeone("ActionLog", "contactId", $oldid, $newid); crpmergeoneignore("TopicInterest", "contactId", $oldid, $newid); crpmergeone("PaperComment", "contactId", $oldid, $newid); // archive duplicate reviews crpmergeoneignore("PaperReview", "contactId", $oldid, $newid); crpmergeone("PaperReview", "requestedBy", $oldid, $newid); crpmergeoneignore("PaperReviewPreference", "contactId", $oldid, $newid); crpmergeone("PaperReviewRefused", "contactId", $oldid, $newid); crpmergeone("PaperReviewRefused", "requestedBy", $oldid, $newid); crpmergeone("ReviewRequest", "requestedBy", $oldid, $newid); crpmergeoneignore("PaperWatch", "contactId", $oldid, $newid); crpmergeoneignore("ReviewRating", "contactId", $oldid, $newid); // Remove the old contact record if ($MergeError == "") { if (!$Conf->q("delete from ContactInfo where contactId={$oldid}")) { $MergeError .= $Conf->db_error_html(true); } } $Conf->qe("unlock tables"); // Update PC settings if we need to if ($old_user->isPC) { $Conf->invalidateCaches(array("pc" => 1)); } }
public function fetch_prows($pids) { global $Conf; $pids = is_array($pids) ? $pids : array($pids); $fetch_pids = array(); foreach ($pids as $p) { if (!isset($this->prows[$p])) { $fetch_pids[] = $p; } } if (count($fetch_pids)) { $q = $Conf->paperQuery($this->contact, array("paperId" => $fetch_pids)); $result = Dbl::qe_raw($q); while ($result && ($prow = PaperInfo::fetch($result, $this->contact))) { $this->prows[$prow->paperId] = $prow; } Dbl::free($result); } }
private function _rows($field_list) { global $Conf; if (!$field_list) { return null; } // prepare query text $this->qopts["scores"] = array_keys($this->qopts["scores"]); if (empty($this->qopts["scores"])) { unset($this->qopts["scores"]); } $pq = $Conf->paperQuery($this->contact, $this->qopts); // make query $result = Dbl::qe_raw($pq); if (!$result) { return null; } // fetch rows $rows = array(); while ($row = PaperInfo::fetch($result, $this->contact)) { $rows[$row->paperId] = $row; } // prepare review query (see also search > getfn == "reviewers") $this->review_list = array(); if (isset($this->qopts["reviewList"]) && !empty($rows)) { $result = Dbl::qe("select Paper.paperId, reviewId, reviewType,\n reviewSubmitted, reviewModified, reviewNeedsSubmit, reviewRound,\n reviewOrdinal,\n PaperReview.contactId, lastName, firstName, email\n from Paper\n join PaperReview using (paperId)\n join ContactInfo on (PaperReview.contactId=ContactInfo.contactId)\n where paperId?a", array_keys($rows)); while ($row = edb_orow($result)) { Contact::set_sorter($row); $this->review_list[$row->paperId][] = $row; } foreach ($this->review_list as &$revlist) { usort($revlist, "PaperList::review_list_compar"); } unset($revlist); } // prepare PC topic interests if (isset($this->qopts["allReviewerPreference"])) { $ord = 0; $pcm = pcMembers(); foreach ($pcm as $pc) { $pc->prefOrdinal = sprintf("-0.%04d", $ord++); $pc->topicInterest = array(); } $result = Dbl::qe("select contactId, topicId, " . $Conf->query_topic_interest() . " from TopicInterest"); while ($row = edb_row($result)) { $pcm[$row[0]]->topicInterest[$row[1]] = $row[2]; } } // analyze rows (usually noop) foreach ($field_list as $fdef) { $fdef->analyze($this, $rows); } // sort rows if (!empty($this->sorters)) { $rows = $this->_sort($rows); if (isset($this->qopts["allReviewScores"])) { $this->_sortReviewOrdinal($rows); } } // set `any->optID` if ($nopts = PaperOption::count_option_list()) { foreach ($rows as $prow) { foreach ($prow->options() as $o) { if (!$this->any["opt{$o->id}"] && $this->contact->can_view_paper_option($prow, $o->option)) { $this->any["opt{$o->id}"] = true; --$nopts; } } if (!$nopts) { break; } } } Dbl::free($result); return $rows; }
private function run() { global $Conf, $Opt, $Me, $Error, $subjectPrefix, $mailer_options; $subject = trim(defval($_REQUEST, "subject", "")); if (substr($subject, 0, strlen($subjectPrefix)) != $subjectPrefix) { $subject = $subjectPrefix . $subject; } $emailBody = $_REQUEST["emailBody"]; $template = array("subject" => $subject, "body" => $emailBody); $rest = array("cc" => $_REQUEST["cc"], "reply-to" => $_REQUEST["replyto"], "no_error_quit" => true); $rest = array_merge($rest, $mailer_options); // test whether this mail is paper-sensitive $mailer = new HotCRPMailer($Me, null, $rest); $prep = $mailer->make_preparation($template, $rest); $paper_sensitive = preg_match('/%[A-Z0-9]+[(%]/', $prep->subject . $prep->body); $q = $this->recip->query($paper_sensitive); if (!$q) { return Conf::msg_error("Bad recipients value"); } $result = $Conf->qe($q); if (!$result) { return; } $recipients = defval($_REQUEST, "recipients", ""); if ($this->sending) { $q = "recipients='" . sqlq($recipients) . "', cc='" . sqlq($_REQUEST["cc"]) . "', replyto='" . sqlq($_REQUEST["replyto"]) . "', subject='" . sqlq($_REQUEST["subject"]) . "', emailBody='" . sqlq($_REQUEST["emailBody"]) . "'"; if ($Conf->sversion >= 79) { $q .= ", q='" . sqlq($_REQUEST["q"]) . "', t='" . sqlq($_REQUEST["t"]) . "'"; } if ($log_result = Dbl::query_raw("insert into MailLog set {$q}")) { $this->mailid_text = " #" . $log_result->insert_id; } $Me->log_activity("Sending mail{$this->mailid_text} \"{$subject}\""); } else { $rest["no_send"] = true; } $mailer = new HotCRPMailer(); $mailer->combination_type = $this->recip->combination_type($paper_sensitive); $fake_prep = new HotCRPMailPreparation(); $fake_prep->fake = true; $last_prep = $fake_prep; $nrows_done = 0; $nrows_left = edb_nrows($result); $nwarnings = 0; $preperrors = array(); $revinform = $recipients == "newpcrev" ? array() : null; while ($row = PaperInfo::fetch($result, $Me)) { ++$nrows_done; $contact = new Contact($row); $rest["newrev_since"] = $this->recip->newrev_since; $mailer->reset($contact, $row, $rest); $prep = $mailer->make_preparation($template, $rest); if ($prep->errors) { foreach ($prep->errors as $lcfield => $hline) { $reqfield = $lcfield == "reply-to" ? "replyto" : $lcfield; $Error[$reqfield] = true; $emsg = Mailer::$email_fields[$lcfield] . " destination isn’t a valid email list: <blockquote><tt>" . htmlspecialchars($hline) . "</tt></blockquote> Make sure email address are separated by commas; put names in \"quotes\" and email addresses in <angle brackets>."; if (!isset($preperrors[$emsg])) { Conf::msg_error($emsg); } $preperrors[$emsg] = true; } } else { if ($this->process_prep($prep, $last_prep, $row)) { if ((!$Me->privChair || @$Opt["chairHidePasswords"]) && !@$last_prep->sensitive) { $srest = array_merge($rest, array("sensitivity" => "display")); $mailer->reset($contact, $row, $srest); $last_prep->sensitive = $mailer->make_preparation($template, $srest); } } } if ($nwarnings != $mailer->nwarnings() || $nrows_done % 5 == 0) { $this->echo_mailinfo($nrows_done, $nrows_left); } if ($nwarnings != $mailer->nwarnings()) { $this->echo_prologue(); $nwarnings = $mailer->nwarnings(); echo "<div id='foldmailwarn{$nwarnings}' class='hidden'><div class='warning'>", join("<br />", $mailer->warnings()), "</div></div>"; $Conf->echoScript("\$\$('mailwarnings').innerHTML = \$\$('foldmailwarn{$nwarnings}').innerHTML;"); } if ($this->sending && $revinform !== null) { $revinform[] = "(paperId={$row->paperId} and contactId={$row->contactId})"; } } $this->process_prep($fake_prep, $last_prep, (object) array("paperId" => -1)); $this->echo_mailinfo($nrows_done, $nrows_left); if (!$this->started && !count($preperrors)) { return Conf::msg_error("No users match “" . $this->recip->unparse() . "” for that search."); } else { if (!$this->started) { return false; } else { if (!$this->sending) { $this->echo_actions(); } } } if ($revinform) { $Conf->qe("update PaperReview set timeRequestNotified=" . time() . " where " . join(" or ", $revinform)); } echo "</div></form>"; $Conf->echoScript("fold('mail', null);"); $Conf->footer(); exit; }
function list_submitted_papers_with_viewable_tags() { global $Conf; $pids = array(); $tag_seeall = $Conf->setting("tag_seeall"); if (!$this->isPC) { return $pids; } else { if (!$this->privChair && $Conf->check_track_sensitivity(Track::VIEW)) { $q = "select p.paperId, pt.paperTags, r.reviewType from Paper p\n left join (select paperId, group_concat(' ', tag, '#', tagIndex order by tag separator '') as paperTags from PaperTag where tag ?a group by paperId) as pt on (pt.paperId=p.paperId)\n left join PaperReview r on (r.paperId=p.paperId and r.contactId={$this->contactId})"; if ($tag_seeall) { $q .= "\nwhere p.timeSubmitted>0"; } else { $q .= "\nleft join PaperConflict pc on (pc.paperId=p.paperId and pc.contactId={$this->contactId})\n where p.timeSubmitted>0 and (pc.conflictType is null or p.managerContactId={$this->contactId})"; } $result = Dbl::qe($q, $Conf->track_tags()); while ($result && ($prow = PaperInfo::fetch($result, $this))) { if ((int) $prow->reviewType >= REVIEW_PC || $Conf->check_tracks($prow, $this, Track::VIEW)) { $pids[] = (int) $prow->paperId; } } Dbl::free($result); return $pids; } else { if (!$this->privChair && !$tag_seeall) { $q = "select p.paperId from Paper p\n left join PaperConflict pc on (pc.paperId=p.paperId and pc.contactId={$this->contactId})\n where p.timeSubmitted>0 and "; if ($Conf->has_any_manager()) { $q .= "(pc.conflictType is null or p.managerContactId={$this->contactId})"; } else { $q .= "pc.conflictType is null"; } } else { if ($this->privChair && $Conf->has_any_manager() && !$tag_seeall) { $q = "select p.paperId from Paper p\n left join PaperConflict pc on (pc.paperId=p.paperId and pc.contactId={$this->contactId})\n where p.timeSubmitted>0 and (pc.conflictType is null or p.managerContactId={$this->contactId} or p.managerContactId=0)"; } else { $q = "select p.paperId from Paper p where p.timeSubmitted>0"; } } } } $result = Dbl::qe($q); while ($row = edb_row($result)) { $pids[] = (int) $row[0]; } Dbl::free($result); return $pids; }
function run(Contact $user, $qreq, $ssel) { global $Conf; $type = $this->islead ? "lead" : "shepherd"; $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection(), "reviewerName" => $type))); $texts = array(); while ($row = PaperInfo::fetch($result, $user)) { if ($row->reviewEmail && ($this->islead ? $user->can_view_lead($row, true) : $user->can_view_shepherd($row, true))) { arrayappend($texts[$row->paperId], [$row->paperId, $row->title, $row->reviewFirstName, $row->reviewLastName, $row->reviewEmail]); } } downloadCSV($ssel->reorder($texts), array("paper", "title", "first", "last", "{$type}email"), "{$type}s"); }
function _search() { global $Conf; if ($this->_matches === false) { return false; } assert($this->_matches === null); if ($this->limitName === "x") { $this->_matches = array(); return true; } // parse and clean the query $qe = $this->_searchQueryType($this->q); //Conf::msg_info(Ht::pre_text(var_export($qe, true))); if (!$qe) { $qe = new SearchTerm("t"); } // apply complex limiters (only current example: "acc" for non-chairs) $limit = $this->limitName; if ($limit === "acc" && !$this->privChair) { $qe = SearchTerm::make_op("and", array($qe, $this->_searchQueryWord("dec:yes", false))); } // apply review rounds (top down, needs separate step) if ($this->reviewAdjust) { $qe = $this->_query_adjust_reviews($qe, null); if ($this->_reviewAdjustError) { $this->warn("Unexpected use of “round:” or “rate:” ignored. Stick to the basics, such as “re:reviewername round:roundname”."); } } //Conf::msg_info(Ht::pre_text(var_export($qe, true))); // collect clauses into tables, columns, and filters $sqi = new SearchQueryInfo(); $sqi->add_table("Paper"); $sqi->add_column("paperId", "Paper.paperId"); // always include columns needed by rights machinery $sqi->add_column("timeSubmitted", "Paper.timeSubmitted"); $sqi->add_column("timeWithdrawn", "Paper.timeWithdrawn"); $sqi->add_column("outcome", "Paper.outcome"); $filters = array(); $this->_clauseTermSet($qe, $sqi, $filters); //Conf::msg_info(Ht::pre_text(var_export($filters, true))); // status limitation parts if ($limit === "rable") { $limitcontact = $this->_reviewer_fixed ? $this->reviewer() : $this->contact; if ($limitcontact->can_accept_review_assignment_ignore_conflict(null)) { $limit = $Conf->can_pc_see_all_submissions() ? "act" : "s"; } else { if (!$limitcontact->isPC) { $limit = "r"; } } } if ($limit === "s" || $limit === "req" || $limit === "acc" || $limit === "und" || $limit === "unm" || $limit === "rable" && !$Conf->can_pc_see_all_submissions()) { $filters[] = "Paper.timeSubmitted>0"; } else { if ($limit === "act" || $limit === "r" || $limit === "rable") { $filters[] = "Paper.timeWithdrawn<=0"; } else { if ($limit === "unsub") { $filters[] = "(Paper.timeSubmitted<=0 and Paper.timeWithdrawn<=0)"; } else { if ($limit === "lead") { $filters[] = "Paper.leadContactId=" . $this->cid; } else { if ($limit === "manager") { if ($this->privChair) { $filters[] = "(Paper.managerContactId=" . $this->cid . " or Paper.managerContactId=0)"; } else { $filters[] = "Paper.managerContactId=" . $this->cid; } $filters[] = "Paper.timeSubmitted>0"; } } } } } // decision limitation parts if ($limit === "acc") { $filters[] = "Paper.outcome>0"; } else { if ($limit === "und") { $filters[] = "Paper.outcome=0"; } } // other search limiters if ($limit === "a") { $filters[] = $this->contact->actAuthorSql("PaperConflict"); $this->needflags |= self::F_AUTHOR; } else { if ($limit === "r") { $filters[] = "MyReview.reviewType is not null"; $this->needflags |= self::F_REVIEWER; } else { if ($limit === "ar") { $filters[] = "(" . $this->contact->actAuthorSql("PaperConflict") . " or (Paper.timeWithdrawn<=0 and MyReview.reviewType is not null))"; $this->needflags |= self::F_AUTHOR | self::F_REVIEWER; } else { if ($limit === "rout") { $filters[] = "MyReview.reviewNeedsSubmit!=0"; $this->needflags |= self::F_REVIEWER; } else { if ($limit === "revs") { $sqi->add_table("Limiter", array("join", "PaperReview")); } else { if ($limit === "req") { $sqi->add_table("Limiter", array("join", "PaperReview", "Limiter.requestedBy={$this->cid} and Limiter.reviewType=" . REVIEW_EXTERNAL)); } else { if ($limit === "unm") { $filters[] = "Paper.managerContactId=0"; } } } } } } } // add common tables: conflicts, my own review, paper blindness if ($this->needflags & (self::F_MANAGER | self::F_NONCONFLICT | self::F_AUTHOR)) { $sqi->add_table("PaperConflict", array("left join", "PaperConflict", "PaperConflict.contactId={$this->cid}")); $sqi->add_column("conflictType", "PaperConflict.conflictType"); } if ($this->needflags & self::F_REVIEWER) { if ($Conf->submission_blindness() == Conf::BLIND_OPTIONAL) { $sqi->add_column("paperBlind", "Paper.blind"); } $qb = ""; if ($tokens = $this->contact->review_tokens()) { $qb = " or MyReview.reviewToken in (" . join(",", $tokens) . ")"; } $sqi->add_table("MyReview", array("left join", "PaperReview", "(MyReview.contactId={$this->cid}{$qb})")); $sqi->add_column("myReviewType", "MyReview.reviewType"); $sqi->add_column("myReviewNeedsSubmit", "MyReview.reviewNeedsSubmit"); $sqi->add_column("myReviewSubmitted", "MyReview.reviewSubmitted"); } // check for annotated order $order_anno_tag = null; if ($qe->type !== "then" && ($sort = $qe->get_float("sort")) && ($tag = self::_check_sort_order_anno($sort))) { $dt = TagInfo::make_defined_tag($tag); if (count($dt->order_anno_list())) { $order_anno_tag = $dt; } } // add permissions tables if we will filter the results $need_filter = $this->needflags & self::F_XVIEW || $Conf->has_tracks() || $qe->type === "then" || $qe->get_float("heading") || $limit === "rable" || $order_anno_tag; if ($need_filter) { $sqi->add_rights_columns(); if ($Conf->submission_blindness() == Conf::BLIND_OPTIONAL) { $sqi->add_column("paperBlind", "Paper.blind"); } } // XXX some of this should be shared with paperQuery if ($need_filter && $Conf->has_track_tags() || get($this->_query_options, "tags") || $order_anno_tag) { $sqi->add_column("paperTags", "(select group_concat(' ', tag, '#', tagIndex separator '') from PaperTag where PaperTag.paperId=Paper.paperId)"); } if (get($this->_query_options, "scores") || get($this->_query_options, "reviewTypes") || get($this->_query_options, "reviewContactIds")) { $j = "group_concat(contactId order by reviewId) reviewContactIds"; $sqi->add_column("reviewContactIds", "R_submitted.reviewContactIds"); if (get($this->_query_options, "reviewTypes")) { $j .= ", group_concat(reviewType order by reviewId) reviewTypes"; $sqi->add_column("reviewTypes", "R_submitted.reviewTypes"); } foreach (get($this->_query_options, "scores") ?: array() as $f) { $j .= ", group_concat({$f} order by reviewId) {$f}Scores"; $sqi->add_column("{$f}Scores", "R_submitted.{$f}Scores"); } $sqi->add_table("R_submitted", array("left join", "(select paperId, {$j} from PaperReview where reviewSubmitted>0 group by paperId)")); } // create query $q = "select "; foreach ($sqi->columns as $colname => $value) { $q .= $value . " " . $colname . ", "; } $q = substr($q, 0, strlen($q) - 2) . "\n from "; foreach ($sqi->tables as $tabname => $value) { if (!$value) { $q .= $tabname; } else { $joiners = array("{$tabname}.paperId=Paper.paperId"); for ($i = 2; $i < count($value); ++$i) { $joiners[] = "(" . $value[$i] . ")"; } $q .= "\n " . $value[0] . " " . $value[1] . " as " . $tabname . " on (" . join("\n and ", $joiners) . ")"; } } if (count($filters)) { $q .= "\n where " . join("\n and ", $filters); } $q .= "\n group by Paper.paperId"; //Conf::msg_info(Ht::pre_text_wrap($q)); // actually perform query $result = Dbl::qe_raw($q); if (!$result) { return $this->_matches = false; } $this->_matches = array(); // correct query, create thenmap, groupmap, highlightmap $need_then = $qe->type === "then"; $this->thenmap = null; if ($need_then && $qe->nthen > 1) { $this->thenmap = array(); } $this->highlightmap = array(); if ($need_filter) { $tag_order = []; while ($row = PaperInfo::fetch($result, $this->cid)) { if (!$this->contact->can_view_paper($row) || $limit === "rable" && !$limitcontact->can_accept_review_assignment_ignore_conflict($row)) { $x = false; } else { if ($need_then) { $x = false; for ($i = 0; $i < $qe->nthen && $x === false; ++$i) { if ($this->_clauseTermCheck($qe->value[$i], $row)) { $x = $i; } } } else { $x = !!$this->_clauseTermCheck($qe, $row); } } if ($x === false) { continue; } $this->_matches[] = $row->paperId; if ($this->thenmap !== null) { $this->thenmap[$row->paperId] = $x; } if ($need_then) { for ($j = $qe->nthen; $j < count($qe->value); ++$j) { if ($this->_clauseTermCheck($qe->value[$j], $row) && $qe->highlights[$j - $qe->nthen] & 1 << $x) { $this->highlightmap[$row->paperId] = $qe->highlight_types[$j - $qe->nthen] . "highlight"; break; } } } if ($order_anno_tag) { if ($row->has_viewable_tag($order_anno_tag->tag, $this->contact)) { $tag_order[] = [$row->paperId, $row->tag_value($order_anno_tag->tag)]; } else { $tag_order[] = [$row->paperId, TAG_INDEXBOUND]; } } } } else { while ($row = $result->fetch_object()) { $this->_matches[] = (int) $row->paperId; } } Dbl::free($result); // add deleted papers explicitly listed by number (e.g. action log) if ($this->_allow_deleted) { $this->_add_deleted_papers($qe); } // view and sort information $this->viewmap = $qe->get_float("view", array()); $this->sorters = array(); $this->_add_sorters($qe, null); if ($qe->type === "then") { for ($i = 0; $i < $qe->nthen; ++$i) { $this->_add_sorters($qe->value[$i], $this->thenmap ? $i : null); } } $this->groupmap = []; if ($qe->type === "then") { for ($i = 0; $i < $qe->nthen; ++$i) { $h = $qe->value[$i]->get_float("heading"); $this->groupmap[$i] = (object) ["heading" => $h, "annoFormat" => 0]; } } else { if ($h = $qe->get_float("heading")) { $this->groupmap[0] = (object) ["heading" => $h, "annoFormat" => 0]; } else { if ($order_anno_tag) { $this->_assign_order_anno($order_anno_tag, $tag_order); $this->is_order_anno = $order_anno_tag->tag; } } } // extract regular expressions and set _reviewer if the query is // about exactly one reviewer, and warn about contradictions $contradictions = array(); $this->_queryExtractInfo($qe, true, false, $contradictions); foreach ($contradictions as $contradiction => $garbage) { $this->warn($contradiction); } // set $this->matchPreg from $this->regex if (!$this->overrideMatchPreg) { $this->matchPreg = array(); foreach (array("ti" => "title", "au" => "authorInformation", "ab" => "abstract", "co" => "collaborators") as $k => $v) { if (isset($this->regex[$k]) && count($this->regex[$k])) { $a = $b = array(); foreach ($this->regex[$k] as $x) { $a[] = $x->preg_utf8; if (isset($x->preg_raw)) { $b[] = $x->preg_raw; } } $x = (object) array("preg_utf8" => join("|", $a)); if (count($a) == count($b)) { $x->preg_raw = join("|", $b); } $this->matchPreg[$v] = $x; } } } return true; }
static function settags_api($user, $qreq, $prow) { global $Conf; if ($qreq->cancelsettags) { json_exit(["ok" => true]); } if ($prow && !$user->can_view_paper($prow)) { json_exit(["ok" => false, "error" => "No such paper."]); } // save tags using assigner $x = array("paper,action,tag"); if ($prow) { if (isset($qreq->tags)) { $x[] = "{$prow->paperId},tag,all#clear"; foreach (TagInfo::split($qreq->tags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t); } } foreach (TagInfo::split((string) $qreq->addtags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t); } foreach (TagInfo::split((string) $qreq->deltags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t . "#clear"); } } else { if (isset($qreq->tagassignment)) { $pids = []; $pid = -1; foreach (preg_split('/[\\s,]+/', $qreq->tagassignment) as $w) { if ($w !== "" && ctype_digit($w)) { $pid = intval($w); } else { if ($w !== "" && $pid > 0) { $x[] = "{$pid},tag," . CsvGenerator::quote($w); $pids[$pid] = true; } } } } } $assigner = new AssignmentSet($user, $user->is_admin_force()); $assigner->parse(join("\n", $x)); $error = join("<br />", $assigner->errors_html()); $ok = $assigner->execute(); // exit if ($ok && $prow) { $prow->load_tags(); $treport = self::tagreport($user, $prow); if ($treport->warnings) { $Conf->warnMsg(join("<br>", $treport->warnings)); } $taginfo = (object) ["ok" => true, "pid" => $prow->paperId]; $prow->add_tag_info_json($taginfo, $user); json_exit($taginfo, true); } else { if ($ok) { $p = []; $result = Dbl::qe_raw($Conf->paperQuery($user, ["paperId" => array_keys($pids), "tags" => true])); while ($prow = PaperInfo::fetch($result, $user)) { $p[$prow->paperId] = (object) []; $prow->add_tag_info_json($p[$prow->paperId], $user); } json_exit(["ok" => true, "p" => $p]); } else { json_exit(["ok" => false, "error" => $error], true); } } }
private function preferences_review($reviewtype) { global $Conf; $time = microtime(true); $this->prefs = array(); foreach ($this->pcm as $cid => $p) { $this->prefs[$cid] = array(); } // first load topics $topicIds = PaperInfo::make_topic_map($this->papersel); $query = "select Paper.paperId, ? contactId,\n coalesce(PaperConflict.conflictType, 0) as conflictType,\n coalesce(PaperReviewPreference.preference, 0) as preference,\n PaperReviewPreference.expertise,\n coalesce(PaperReview.reviewType, 0) as myReviewType,\n coalesce(PaperReview.reviewSubmitted, 0) as myReviewSubmitted,\n Paper.outcome,\n coalesce(PRR.contactId, 0) as refused,\n Paper.managerContactId\n from Paper\n left join PaperConflict on (PaperConflict.paperId=Paper.paperId and PaperConflict.contactId=?)\n left join PaperReviewPreference on (PaperReviewPreference.paperId=Paper.paperId and PaperReviewPreference.contactId=?)\n left join PaperReview on (PaperReview.paperId=Paper.paperId and PaperReview.contactId=?)\n left join PaperReviewRefused PRR on (PRR.paperId=Paper.paperId and PRR.contactId=?)\n where Paper.paperId ?a\n group by Paper.paperId"; $nmade = 0; foreach ($this->pcm as $cid => $p) { $result = Dbl::qe($query, $cid, $cid, $cid, $cid, $cid, $this->papersel); while ($row = PaperInfo::fetch($result, true)) { $row->topicIds = get($topicIds, $row->paperId); $topic_interest_score = $row->topic_interest_score($p); if (($exp = $row->expertise) !== null) { $exp = (int) $exp; } $this->prefinfo["{$row->paperId} {$row->contactId}"] = array($row->preference, $exp, $topic_interest_score); if ($row->myReviewType == $reviewtype) { $pref = self::POLDASSIGN; } else { if ($row->myReviewType > 0) { $pref = self::POTHERASSIGN; } else { if ($row->conflictType > 0 || $row->refused > 0 || !$p->can_accept_review_assignment($row)) { $pref = self::PNOASSIGN; } else { if ($row->preference) { $pref = max($row->preference, -1000); } else { $pref = $topic_interest_score / 100; } } } } $this->prefs[$row->contactId][$row->paperId] = $pref; } Dbl::free($result); ++$nmade; if ($nmade % 4 == 0) { $this->set_progress(sprintf("Loading reviewer preferences (%d%% done)", (int) ($nmade * 100 / count($this->pcm) + 0.5))); } } $this->make_pref_groups(); // need to populate review assignments for badpairs not in `pcm` foreach ($this->badpairs as $cid => $x) { if (!isset($this->pcm[$cid])) { $result = Dbl::qe("select paperId from PaperReview where contactId=? and paperId ?a", $cid, $this->papersel); while ($row = edb_row($result)) { $this->prefs[$cid][$row[0]] = self::POLDASSIGN; } Dbl::free($result); } } // mark badpairs as noassign foreach ($this->badpairs as $cid => $bp) { if (isset($this->pcm[$cid])) { foreach ($this->papersel as $pid) { if ($this->prefs[$cid][$pid] < self::PMIN) { continue; } foreach ($bp as $cid2 => $x) { if ($this->prefs[$cid2][$pid] <= self::POTHERASSIGN) { $this->prefs[$cid2][$pid] = self::PNOASSIGN; } } } } } $this->profile["preferences"] = microtime(true) - $time; }
private function _combine_data($result) { global $Me; $data = []; if ($this->fx->result_format() === Fexpr::FREVIEWER) { $this->_prepare_reviewer_color($Me); } $fxf = $this->fx->compile_function($Me); list($fytrack, $fycombine) = $this->fy->compile_combine_functions($Me); $reviewf = null; if ($this->fx->needs_review() || $this->fy->datatypes) { $reviewf = Formula::compile_indexes_function($Me, ($this->fx->needs_review() ? $this->fx->datatypes : 0) | $this->fy->datatypes); } while ($prow = PaperInfo::fetch($result, $Me)) { if (!$Me->can_view_paper($prow)) { continue; } $queries = $this->papermap[$prow->paperId]; $s = $ps = $this->_paper_style($prow); $revs = $reviewf ? $reviewf($prow, $Me) : [null]; foreach ($revs as $rcid) { if (($x = $fxf($prow, $rcid, $Me)) === null) { continue; } if ($ps === self::REVIEWER_COLOR) { $s = get($this->reviewer_color, $d[0]) ?: ""; } $d = [$x, $fytrack($prow, $rcid, $Me), $prow->paperId, $s]; if ($rcid && ($o = $prow->review_ordinal($rcid))) { $d[2] .= unparseReviewOrdinal($o); } foreach ($queries as $q) { $q && ($d[4] = $q); $data[] = $d; } } } $is_sum = $this->fy->is_sum(); usort($data, "FormulaGraph::barchart_compare"); $ndata = []; for ($i = 0; $i != count($data); $i = $j) { $d = [$data[$i][0], [$data[$i][1]], [$data[$i][2]], $data[$i][3], get($data[$i], 4)]; for ($j = $i + 1; $j != count($data) && $data[$j][0] == $d[0] && get($data[$j], 4) == $d[4] && (!$is_sum || $data[$j][3] == $d[3]); ++$j) { $d[1][] = $data[$j][1]; $d[2][] = $data[$j][2]; if ($d[3] && $d[3] != $data[$j][3]) { $d[3] = ""; } } $d[1] = $fycombine($d[1]); if (!$d[4]) { array_pop($d); $d[3] || array_pop($d); } $ndata[] = $d; } return $ndata; }
static function pcassignments_csv_data($user, $selection) { global $Conf; $pcm = pcMembers(); $round_list = $Conf->round_list(); $reviewnames = array(REVIEW_PC => "pcreview", REVIEW_SECONDARY => "secondary", REVIEW_PRIMARY => "primary"); $any_round = false; $texts = array(); $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $selection, "assignments" => 1))); while ($prow = PaperInfo::fetch($result, $user)) { if (!$user->allow_administer($prow)) { $texts[] = array(); $texts[] = array("paper" => $prow->paperId, "action" => "none", "title" => "You cannot override your conflict with this paper"); } else { if ($prow->all_reviewers()) { $texts[] = array(); $texts[] = array("paper" => $prow->paperId, "action" => "clearreview", "email" => "#pc", "round" => "any", "title" => $prow->title); foreach ($prow->all_reviewers() as $cid) { if (($pc = get($pcm, $cid)) && ($rtype = $prow->review_type($cid)) >= REVIEW_PC) { $round = $prow->review_round($cid); $round_name = $round ? $round_list[$round] : "none"; $any_round = $any_round || $round != 0; $texts[] = array("paper" => $prow->paperId, "action" => $reviewnames[$rtype], "email" => $pc->email, "round" => $round_name); } } } } } $header = array("paper", "action", "email"); if ($any_round) { $header[] = "round"; } $header[] = "title"; return [$header, $texts]; }
function run(Contact $user, $qreq, $ssel) { global $Conf; $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection(), "topics" => 1))); $texts = array(); $tmap = $Conf->topic_map(); while ($row = PaperInfo::fetch($result, $user)) { if ($user->can_view_paper($row)) { $out = array(); foreach ($row->topics() as $t) { $out[] = [$row->paperId, $row->title, $tmap[$t]]; } if (!count($out)) { $out[] = [$row->paperId, $row->title, "<none>"]; } arrayappend($texts[$row->paperId], $out); } } downloadCSV($ssel->reorder($texts), array("paper", "title", "topic"), "topics"); }
function comment_rows($q, $contact) { $result = $this->qe($q); $crows = array(); while ($row = PaperInfo::fetch($result, $contact)) { $crows[$row->commentId] = $row; if (isset($row->commentContactId)) { $cid = $row->commentContactId; } else { $cid = $row->contactId; } $row->threadContacts = array($cid => 1); for ($r = $row; defval($r, "replyTo", 0) && isset($crows[$r->replyTo]); $r = $crows[$r->replyTo]) { /* do nothing */ } $row->threadHead = $r->commentId; $r->threadContacts[$cid] = 1; } Dbl::free($result); foreach ($crows as $row) { if ($row->threadHead != $row->commentId) { $row->threadContacts = $crows[$row->threadHead]->threadContacts; } } return $crows; }
// Redirect if requested user isn't loaded user. if (!$Acct || isset($_REQUEST["u"]) && $_REQUEST["u"] !== (string) $Acct->contactId && strcasecmp($_REQUEST["u"], $Acct->email) && ($Acct->contactId || $_REQUEST["u"] !== "new") || isset($_REQUEST["profile_contactid"]) && $_REQUEST["profile_contactid"] !== (string) $Acct->contactId) { if (!$Acct) { Conf::msg_error("Invalid user."); } else { if (isset($_REQUEST["register"]) || isset($_REQUEST["bulkregister"])) { Conf::msg_error("You’re logged in as a different user now, so your changes were ignored."); } } unset($_REQUEST["u"], $_REQUEST["register"], $_REQUEST["bulkregister"]); redirectSelf(); } $need_highlight = false; if (($Acct->contactId != $Me->contactId || !$Me->has_database_account()) && $Acct->has_email() && !$Acct->firstName && !$Acct->lastName && !$Acct->affiliation && !isset($_REQUEST["post"])) { $result = $Conf->qe("select Paper.paperId, authorInformation from Paper join PaperConflict on (PaperConflict.paperId=Paper.paperId and PaperConflict.contactId={$Acct->contactId} and PaperConflict.conflictType>=" . CONFLICT_AUTHOR . ")"); while ($prow = PaperInfo::fetch($result, $Me)) { foreach ($prow->author_list() as $au) { if (strcasecmp($au->email, $Acct->email) == 0 && ($au->firstName || $au->lastName || $au->affiliation)) { if (!$Acct->firstName && $au->firstName) { $Acct->firstName = $au->firstName; $need_highlight = true; } if (!$Acct->lastName && $au->lastName) { $Acct->lastName = $au->lastName; $need_highlight = true; } if (!$Acct->affiliation && $au->affiliation) { $Acct->affiliation = $au->affiliation; $need_highlight = true; } }
function run(Contact $user, $qreq, $ssel) { global $Conf; $mt = $qreq->assignfn; $mpc = (string) $qreq->markpc; $pc = null; if ($mpc != "" && $mpc != "0") { $pc = Contact::find_by_email($mpc); } if ($mt == "auto") { $t = in_array($qreq->t, array("acc", "s")) ? $qreq->t : "all"; $q = join("+", $ssel->selection()); go(hoturl("autoassign", "pap={$q}&t={$t}&q={$q}")); } else { if ($mt == "lead" || $mt == "shepherd") { if ($user->assign_paper_pc($ssel->selection(), $mt, $pc)) { $Conf->confirmMsg(ucfirst(pluralx($ssel->selection(), $mt)) . " set."); } else { if ($OK) { $Conf->confirmMsg("No changes."); } } } else { if (!$pc) { Conf::msg_error("“" . htmlspecialchars($mpc) . "” is not a PC member."); } else { if ($mt == "conflict" || $mt == "unconflict") { if ($mt == "conflict") { Dbl::qe("insert into PaperConflict (paperId, contactId, conflictType) (select paperId, ?, ? from Paper where paperId" . $ssel->sql_predicate() . ") on duplicate key update conflictType=greatest(conflictType, values(conflictType))", $pc->contactId, CONFLICT_CHAIRMARK); $user->log_activity("Mark conflicts with {$mpc}", $ssel->selection()); } else { Dbl::qe("delete from PaperConflict where PaperConflict.conflictType<? and contactId=? and (paperId" . $ssel->sql_predicate() . ")", CONFLICT_AUTHOR, $pc->contactId); $user->log_activity("Remove conflicts with {$mpc}", $ssel->selection()); } } else { if (substr($mt, 0, 6) == "assign" && ($asstype = substr($mt, 6)) && isset(ReviewForm::$revtype_names[$asstype])) { Dbl::qe_raw("lock tables PaperConflict write, PaperReview write, PaperReviewRefused write, Paper write, ActionLog write, Settings write"); $result = Dbl::qe_raw("select Paper.paperId, reviewId, reviewType, reviewModified, conflictType from Paper left join PaperReview on (Paper.paperId=PaperReview.paperId and PaperReview.contactId=" . $pc->contactId . ") left join PaperConflict on (Paper.paperId=PaperConflict.paperId and PaperConflict.contactId=" . $pc->contactId . ") where Paper.paperId" . $ssel->sql_predicate()); $conflicts = array(); $assigned = array(); $nworked = 0; while ($row = PaperInfo::fetch($result, $user)) { if ($asstype && $row->conflictType > 0) { $conflicts[] = $row->paperId; } else { if ($asstype && $row->reviewType >= REVIEW_PC && $asstype != $row->reviewType) { $assigned[] = $row->paperId; } else { $user->assign_review($row->paperId, $pc->contactId, $asstype); $nworked++; } } } if (count($conflicts)) { Conf::msg_error("Some papers were not assigned because of conflicts (" . join(", ", $conflicts) . "). If these conflicts are in error, remove them and try to assign again."); } if (count($assigned)) { Conf::msg_error("Some papers were not assigned because the PC member already had an assignment (" . join(", ", $assigned) . ")."); } if ($nworked) { $Conf->confirmMsg($asstype == 0 ? "Unassigned reviews." : "Assigned reviews."); } Dbl::qe_raw("unlock tables"); $Conf->update_rev_tokens_setting(false); } } } } } }
function content($fieldId, $row) { global $Conf; switch ($fieldId) { case self::FIELD_NAME: $t = Text::name_html($row); if (trim($t) == "") { $t = "[No name]"; } $t = '<span class="taghl">' . $t . '</span>'; if ($this->contact->privChair) { $t = "<a href=\"" . hoturl("profile", "u=" . urlencode($row->email) . $this->contactLinkArgs) . "\"" . ($row->disabled ? " class='uu'" : "") . ">{$t}</a>"; } if ($row->roles & Contact::ROLE_CHAIR) { $t .= ' <span class="pcrole">(chair)</span>'; } else { if (($row->roles & (Contact::ROLE_ADMIN | Contact::ROLE_PC)) == (Contact::ROLE_ADMIN | Contact::ROLE_PC)) { $t .= ' <span class="pcrole">(PC, sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_ADMIN) { $t .= ' <span class="pcrole">(sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_PC && $this->limit != "pc") { $t .= ' <span class="pcrole">(PC)</span>'; } } } } if ($this->contact->privChair && $row->email != $this->contact->email) { $t .= " <a href=\"" . hoturl("index", "actas=" . urlencode($row->email)) . "\">" . Ht::img("viewas.png", "[Act as]", array("title" => "Act as " . Text::name_text($row))) . "</a>"; } if ($row->disabled && $this->contact->isPC) { $t .= ' <span class="hint">(disabled)</span>'; } return $t; case self::FIELD_EMAIL: if (!$this->contact->isPC) { return ""; } $e = htmlspecialchars($row->email); if (strpos($row->email, "@") === false) { return $e; } else { return "<a href=\"mailto:{$e}\">{$e}</a>"; } case self::FIELD_AFFILIATION: case self::FIELD_AFFILIATION_ROW: return htmlspecialchars($row->affiliation); case self::FIELD_LASTVISIT: if (!$row->lastLogin) { return "Never"; } return $Conf->printableTimeShort($row->lastLogin); case self::FIELD_SELECTOR: case self::FIELD_SELECTOR_ON: $this->any->sel = true; $c = ""; if ($fieldId == self::FIELD_SELECTOR_ON) { $c = " checked='checked'"; } return "<input type='checkbox' class='cb' name='pap[]' value='{$row->contactId}' tabindex='1' id='psel{$this->count}' onclick='rangeclick(event,this)' {$c}/>"; case self::FIELD_HIGHTOPICS: case self::FIELD_LOWTOPICS: if (!defval($row, "topicIds")) { return ""; } $wanthigh = $fieldId == self::FIELD_HIGHTOPICS; $topics = array_combine(explode(",", $row->topicIds), explode(",", $row->topicInterest)); $nt = $nti = array(); foreach ($topics as $k => $v) { if ($wanthigh ? $v > 0 : $v < 0) { $nt[] = $k; $nti[] = $v; } } if (count($nt)) { return PaperInfo::unparse_topic_list_html($nt, $nti, true); } else { return ""; } case self::FIELD_REVIEWS: if (!$row->numReviews && !$row->numReviewsSubmitted) { return ""; } $a1 = "<a href=\"" . hoturl("search", "t=s&q=re:" . urlencode($row->email)) . "\">"; if ($row->numReviews == $row->numReviewsSubmitted) { return "{$a1}<b>{$row->numReviewsSubmitted}</b></a>"; } else { return "{$a1}<b>{$row->numReviewsSubmitted}</b>/{$row->numReviews}</a>"; } case self::FIELD_LEADS: if (!$row->numLeads) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=lead:" . urlencode($row->email)) . "\">{$row->numLeads}</a>"; case self::FIELD_SHEPHERDS: if (!$row->numShepherds) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=shepherd:" . urlencode($row->email)) . "\">{$row->numShepherds}</a>"; case self::FIELD_REVIEW_RATINGS: if (!$row->numReviews && !$row->numReviewsSubmitted || !$row->numRatings) { return ""; } $a = array(); $b = array(); if ($row->sumRatings > 0) { $a[] = $row->sumRatings . " positive"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:%2B") . "\">+" . $row->sumRatings . "</a>"; } if ($row->sumRatings < $row->numRatings) { $a[] = $row->numRatings - $row->sumRatings . " negative"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:-") . "\">−" . ($row->numRatings - $row->sumRatings) . "</a>"; } return "<span class='hastitle' title='" . join(", ", $a) . "'>" . join(" ", $b) . "</span>"; case self::FIELD_PAPERS: if (!$row->paperIds) { return ""; } $x = explode(",", $row->paperIds); sort($x, SORT_NUMERIC); foreach ($x as &$v) { $v = '<a href="' . hoturl("paper", "p={$v}") . '">' . $v . '</a>'; } $ls = "p/s/"; if ($this->limit == "auuns" || $this->limit == "all") { $ls = "p/all/"; } $ls = htmlspecialchars($ls . urlencode("au:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $x) . '</div>'; case self::FIELD_REVIEW_PAPERS: if (!$row->paperIds) { return ""; } $pids = explode(",", $row->paperIds); $rids = explode(",", $row->reviewIds); $ords = explode(",", $row->reviewOrdinals); $spids = $pids; sort($spids, SORT_NUMERIC); $m = array(); for ($i = 0; $i != count($pids); ++$i) { if ($ords[$i]) { $url = hoturl("paper", "p=" . $pids[$i] . "#r" . $pids[$i] . unparseReviewOrdinal($ords[$i])); } else { $url = hoturl("review", "p=" . $pids[$i] . "&r=" . $rids[$i]); } $m[$pids[$i]] = "<a href=\"{$url}\">" . $pids[$i] . "</a>"; } ksort($m, SORT_NUMERIC); $ls = htmlspecialchars("p/s/" . urlencode("re:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $m) . '</div>'; case self::FIELD_TAGS: if ($this->contact->isPC && ($tags = $row->viewable_tags($this->contact))) { $x = []; foreach (TagInfo::split($tags) as $t) { $x[] = '<a class="qq nw" href="' . hoturl("users", "t=%23" . TagInfo::base($t)) . '">' . $this->tagger->unparse_hashed($t) . '</a>'; } return join(" ", $x); } return ""; case self::FIELD_COLLABORATORS: if (!$this->contact->isPC || !($row->roles & Contact::ROLE_PC)) { return ""; } $t = array(); foreach (explode("\n", $row->collaborators) as $collab) { if (preg_match(',\\A(.*?)\\s*(\\(.*\\))\\s*\\z,', $collab, $m)) { $t[] = '<span class="nw">' . htmlspecialchars($m[1]) . ' <span class="auaff">' . htmlspecialchars($m[2]) . '</span></span>'; } else { if (($collab = trim($collab)) !== "" && strcasecmp($collab, "None")) { $t[] = '<span class="nw">' . htmlspecialchars($collab) . '</span>'; } } } return join("; ", $t); default: $f = ReviewForm::field($fieldId); if (!$f) { return ""; } if (!($row->roles & Contact::ROLE_PC) && !$this->contact->privChair && $this->limit != "req") { return ""; } $v = scoreCounts($row->{$fieldId}, $this->scoreMax[$fieldId]); $m = ""; if ($v->n > 0) { $m = $f->unparse_graph($v, 2, 0); } return $m; } }