コード例 #1
0
 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;
 }
コード例 #2
0
 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));
     }
 }
コード例 #3
0
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();
}
コード例 #4
0
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]);
}
コード例 #5
0
 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;
 }
コード例 #6
0
 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]);
 }
コード例 #7
0
 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];
     }
 }
コード例 #8
0
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));
    }
}
コード例 #9
0
 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);
     }
 }
コード例 #10
0
 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;
 }
コード例 #11
0
 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 &lt;angle brackets&gt;.";
                 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;
 }
コード例 #12
0
 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;
 }
コード例 #13
0
 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");
 }
コード例 #14
0
 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;
 }
コード例 #15
0
 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);
         }
     }
 }
コード例 #16
0
 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;
 }
コード例 #17
0
 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;
 }
コード例 #18
0
 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];
 }
コード例 #19
0
 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");
 }
コード例 #20
0
 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;
 }
コード例 #21
0
// 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;
                }
            }
コード例 #22
0
 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);
                     }
                 }
             }
         }
     }
 }
コード例 #23
0
 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&amp;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&amp;q=lead:" . urlencode($row->email)) . "\">{$row->numLeads}</a>";
         case self::FIELD_SHEPHERDS:
             if (!$row->numShepherds) {
                 return "";
             }
             return "<a href=\"" . hoturl("search", "t=s&amp;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:-") . "\">&minus;" . ($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] . "&amp;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;
     }
 }