Example #1
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;
 }
function proposeReview($email, $round)
{
    global $Conf, $Me, $Now, $prow, $rrows;
    $email = trim($email);
    $name = trim($_REQUEST["name"]);
    $reason = trim($_REQUEST["reason"]);
    $reqId = Contact::id_by_email($email);
    Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write, ReviewRequest write, ContactInfo read, PaperConflict read");
    // NB caller unlocks tables on error
    if ($reqId > 0 && !($result = requestReviewChecks(htmlspecialchars($email), $reqId))) {
        return $result;
    }
    // add review request
    $result = Dbl::qe("insert into ReviewRequest set paperId={$prow->paperId},\n        name=?, email=?, requestedBy={$Me->contactId}, reason=?, reviewRound=?\n        on duplicate key update paperId=paperId", $name, $email, $reason, $round);
    // send confirmation email
    HotCRPMailer::send_manager("@proposereview", $prow, array("permissionContact" => $Me, "cc" => Text::user_email_to($Me), "requester_contact" => $Me, "reviewer_contact" => (object) array("fullName" => $name, "email" => $email), "reason" => $reason));
    // confirmation message
    $Conf->confirmMsg("Proposed that " . htmlspecialchars("{$name} <{$email}>") . " review paper #{$prow->paperId}.  The chair must approve this proposal for it to take effect.");
    Dbl::qx_raw("unlock tables");
    $Me->log_activity("Logged proposal for {$email} to review", $prow);
    return true;
}
function expandMailTemplate($name, $default)
{
    global $null_mailer;
    if (!isset($null_mailer)) {
        $null_mailer = new HotCRPMailer(null, null, array("width" => false));
    }
    return $null_mailer->expand_template($name, $default);
}
 function sendAccountInfo($sendtype, $sensitive)
 {
     global $Conf, $Opt;
     assert(!$this->disabled);
     $rest = array();
     if ($sendtype == "create" && $this->prefer_contactdb_password()) {
         $template = "@activateaccount";
     } else {
         if ($sendtype == "create") {
             $template = "@createaccount";
         } else {
             if ($this->plaintext_password() && ($Opt["safePasswords"] <= 1 || $sendtype != "forgot")) {
                 $template = "@accountinfo";
             } else {
                 if ($this->contactDbId && $this->prefer_contactdb_password()) {
                     $capmgr = $Conf->capability_manager("U");
                 } else {
                     $capmgr = $Conf->capability_manager();
                 }
                 $rest["capability"] = $capmgr->create(CAPTYPE_RESETPASSWORD, array("user" => $this, "timeExpires" => time() + 259200));
                 $Conf->log("Created password reset " . substr($rest["capability"], 0, 8) . "...", $this);
                 $template = "@resetpassword";
             }
         }
     }
     $mailer = new HotCRPMailer($this, null, $rest);
     $prep = $mailer->make_preparation($template, $rest);
     if ($prep->sendable || !$sensitive || get($Opt, "debugShowSensitiveEmail")) {
         Mailer::send_preparation($prep);
         return $template;
     } else {
         Conf::msg_error("Mail cannot be sent to " . htmlspecialchars($this->email) . " at this time.");
         return false;
     }
 }
function crpmerge($MiniMe)
{
    global $Conf, $Me, $MergeError;
    if (!$MiniMe->contactId && !$Me->contactId) {
        return $MergeError = "Neither of those accounts has any data associated with this conference.";
    }
    // XXX `act as` merging might be useful?
    if (strcasecmp($Me->email, $_SESSION["trueuser"]->email)) {
        return $MergeError = "You can’t merge accounts when acting as a different user.";
    }
    // determine old & new users
    if (@$_REQUEST["prefer"]) {
        list($old_user, $new_user) = [$Me, $MiniMe];
    } else {
        list($old_user, $new_user) = [$MiniMe, $Me];
    }
    // send mail at start of process
    HotCRPMailer::send_to($old_user, "@mergeaccount", null, array("cc" => Text::user_email_to($new_user), "other_contact" => $new_user));
    // actually merge users or change email
    if ($old_user->contactId && $new_user->contactId) {
        crpmerge_database($old_user, $new_user);
    } else {
        if ($old_user->contactId) {
            $user_status = new UserStatus(["send_email" => false]);
            $user_status->save($user_status->user_to_json($new_user), $old_user);
        }
    }
    // update trueuser
    if (strcasecmp($_SESSION["trueuser"]->email, $new_user->email)) {
        $_SESSION["trueuser"] = (object) ["email" => $new_user->email];
    }
    if ($MergeError == "") {
        $Conf->confirmMsg("Merged account " . htmlspecialchars($old_user->email) . ".");
        $new_user->log_activity("Merged account {$old_user->email}");
        go(hoturl("index"));
    } else {
        $new_user->log_activity("Merged account {$old_user->email} with errors");
        $MergeError .= $Conf->db_error_html(true);
    }
}
Example #6
0
function update_paper($pj, $opj, $qreq, $action, $diffs)
{
    global $Conf, $Me, $Opt, $OK, $Error, $prow;
    // XXX lock tables
    $ps = new PaperStatus($Me);
    $saved = $ps->save_paper_json($pj);
    if (!$saved && !$prow && count($qreq->_FILES)) {
        $ps->set_error_html("paper", "<strong>Your uploaded files were ignored.</strong>");
    }
    if (!get($pj, "collaborators") && $Conf->setting("sub_collab")) {
        $field = $Conf->setting("sub_pcconf") ? "Other conflicts" : "Potential conflicts";
        $ps->set_warning_html("collaborators", "Please enter the authors’ potential conflicts in the {$field} field. If none of the authors have potential conflicts, just enter “None”.");
    }
    $Error = $ps->error_fields();
    if (!$saved) {
        $emsg = $ps->error_html();
        Conf::msg_error("There were errors in saving your paper. Please fix them and try again." . (count($emsg) ? "<ul><li>" . join("</li><li>", $emsg) . "</li></ul>" : ""));
        return false;
    }
    // note differences in contacts
    $contacts = $ocontacts = [];
    foreach (get($pj, "contacts", []) as $v) {
        $contacts[] = strtolower(is_string($v) ? $v : $v->email);
    }
    if ($opj && get($opj, "contacts")) {
        foreach ($opj->contacts as $v) {
            $ocontacts[] = strtolower($v->email);
        }
    }
    sort($contacts);
    sort($ocontacts);
    if (json_encode($contacts) !== json_encode($ocontacts)) {
        $diffs["contacts"] = true;
    }
    // submit paper if no error so far
    $_REQUEST["paperId"] = $_GET["paperId"] = $qreq->paperId = $pj->pid;
    loadRows();
    if ($action === "final") {
        $submitkey = "timeFinalSubmitted";
        $storekey = "finalPaperStorageId";
    } else {
        $submitkey = "timeSubmitted";
        $storekey = "paperStorageId";
    }
    $wasSubmitted = $opj && get($opj, "submitted");
    if (get($pj, "submitted") || $Conf->can_pc_see_all_submissions()) {
        $Conf->update_papersub_setting(true);
    }
    if ($wasSubmitted != get($pj, "submitted")) {
        $diffs["submission"] = 1;
    }
    // confirmation message
    if ($action == "final") {
        $actiontext = "Updated final version of";
        $template = "@submitfinalpaper";
    } else {
        if (get($pj, "submitted") && !$wasSubmitted) {
            $actiontext = "Submitted";
            $template = "@submitpaper";
        } else {
            if (!$opj) {
                $actiontext = "Registered new";
                $template = "@registerpaper";
            } else {
                $actiontext = "Updated";
                $template = "@updatepaper";
            }
        }
    }
    // additional information
    $notes = array();
    if ($action == "final") {
        if ($prow->{$submitkey} === null || $prow->{$submitkey} <= 0) {
            $notes[] = "The final version has not yet been submitted.";
        }
        $deadline = $Conf->printableTimeSetting("final_soft", "span");
        if ($deadline != "N/A" && $Conf->deadlinesAfter("final_soft")) {
            $notes[] = "<strong>The deadline for submitting final versions was {$deadline}.</strong>";
        } else {
            if ($deadline != "N/A") {
                $notes[] = "You have until {$deadline} to make further changes.";
            }
        }
    } else {
        if (get($pj, "submitted")) {
            $notes[] = "You will receive email when reviews are available.";
        } else {
            if ($prow->size == 0 && !opt("noPapers")) {
                $notes[] = "The submission has not yet been uploaded.";
            } else {
                if ($Conf->setting("sub_freeze") > 0) {
                    $notes[] = "The submission has not yet been completed.";
                } else {
                    $notes[] = "The submission is marked as not ready for review.";
                }
            }
        }
        $deadline = $Conf->printableTimeSetting("sub_update", "span");
        if ($deadline != "N/A" && ($prow->timeSubmitted <= 0 || $Conf->setting("sub_freeze") <= 0)) {
            $notes[] = "Further updates are allowed until {$deadline}.";
        }
        $deadline = $Conf->printableTimeSetting("sub_sub", "span");
        if ($deadline != "N/A" && $prow->timeSubmitted <= 0) {
            $notes[] = "<strong>If the submission " . ($Conf->setting("sub_freeze") > 0 ? "is not completed" : "is not ready for review") . " by {$deadline}, it will not be considered.</strong>";
        }
    }
    $notes = join(" ", $notes);
    $webnotes = "";
    if (count($ps->error_html())) {
        $webnotes .= " <ul><li>" . join("</li><li>", $ps->error_html()) . "</li></ul>";
    }
    if (!count($diffs)) {
        $Conf->warnMsg("There were no changes to submission #{$prow->paperId}. " . $notes . $webnotes);
        return true;
    }
    // HTML confirmation
    if ($prow->{$submitkey} > 0) {
        $Conf->confirmMsg($actiontext . " submission #{$prow->paperId}. " . $notes . $webnotes);
    } else {
        $Conf->warnMsg($actiontext . " submission #{$prow->paperId}. " . $notes . $webnotes);
    }
    // mail confirmation to all contact authors
    if (!$Me->privChair || $qreq->doemail > 0) {
        $options = array("infoNames" => 1);
        if ($Me->privChair && $prow->conflictType < CONFLICT_AUTHOR) {
            $options["adminupdate"] = true;
        }
        if ($Me->privChair && isset($qreq->emailNote)) {
            $options["reason"] = $qreq->emailNote;
        }
        if ($notes !== "") {
            $options["notes"] = preg_replace(",</?(?:span.*?|strong)>,", "", $notes) . "\n\n";
        }
        HotCRPMailer::send_contacts($template, $prow, $options);
    }
    // other mail confirmations
    if ($action == "final" && $OK && !count($Error)) {
        $prow->notify(WATCHTYPE_FINAL_SUBMIT, "final_submit_watch_callback", $Me);
    }
    $Me->log_activity($actiontext, $prow->paperId);
    return true;
}
 function cleanup(AssignmentSet $aset)
 {
     global $Conf;
     if ($this->notify) {
         $reviewer = Contact::find_by_id($this->cid);
         $prow = $Conf->paperRow(array("paperId" => $this->pid, "reviewer" => $this->cid), $reviewer);
         HotCRPMailer::send_to($reviewer, $this->notify, $prow);
     }
 }
<?php

// bulkassign.php -- HotCRP bulk paper assignment page
// HotCRP is Copyright (c) 2006-2016 Eddie Kohler and Regents of the UC
// Distributed under an MIT-like license; see LICENSE
require_once "src/initweb.php";
require_once "src/papersearch.php";
require_once "src/assigners.php";
if (!$Me->is_manager()) {
    $Me->escape();
}
if (check_post()) {
    header("X-Accel-Buffering: no");
}
// NGINX: do not hold on to file
$null_mailer = new HotCRPMailer(null, null, array("requester_contact" => $Me, "other_contact" => $Me, "reason" => "", "width" => false));
$Error = array();
$_GET["rev_roundtag"] = $_POST["rev_roundtag"] = $_REQUEST["rev_roundtag"] = (string) $Conf->sanitize_round_name(req("rev_roundtag"));
function assignment_defaults()
{
    $defaults = array("action" => req("default_action"), "round" => $_REQUEST["rev_roundtag"]);
    if (req("requestreview_notify") && req("requestreview_body")) {
        $defaults["extrev_notify"] = ["subject" => req("requestreview_subject"), "body" => req("requestreview_body")];
    }
    return $defaults;
}
$csv_lineno = 0;
$csv_preparing = false;
$csv_started = 0;
function keep_browser_alive($assignset, $lineno, $line)
{
function save_user($cj, $user_status, $Acct, $allow_modification)
{
    global $Conf, $Me, $Opt, $OK, $newProfile;
    if ($newProfile) {
        $Acct = null;
    }
    // check for missing fields
    UserStatus::normalize_name($cj);
    if ($newProfile && !isset($cj->email)) {
        $user_status->set_error("email", "Email address required.");
        return false;
    }
    // check email
    if ($newProfile || $cj->email != $Acct->email) {
        if ($new_acct = Contact::find_by_email($cj->email)) {
            if ($allow_modification) {
                $cj->id = $new_acct->contactId;
            } else {
                $msg = "Email address “" . htmlspecialchars($cj->email) . "” is already in use.";
                if ($Me->privChair) {
                    $msg = str_replace("an account", "<a href=\"" . hoturl("profile", "u=" . urlencode($cj->email)) . "\">an account</a>", $msg);
                }
                if (!$newProfile) {
                    $msg .= " You may want to <a href=\"" . hoturl("mergeaccounts") . "\">merge these accounts</a>.";
                }
                return $user_status->set_error("email", $msg);
            }
        } else {
            if (Contact::external_login()) {
                if ($cj->email === "") {
                    return $user_status->set_error("email", "Not a valid username.");
                }
            } else {
                if ($cj->email === "") {
                    return $user_status->set_error("email", "You must supply an email address.");
                } else {
                    if (!validate_email($cj->email)) {
                        return $user_status->set_error("email", "“" . htmlspecialchars($cj->email) . "” is not a valid email address.");
                    }
                }
            }
        }
        if (!$newProfile && !$Me->privChair) {
            $old_preferredEmail = $Acct->preferredEmail;
            $Acct->preferredEmail = $cj->email;
            $capmgr = $Conf->capability_manager();
            $rest = array("capability" => $capmgr->create(CAPTYPE_CHANGEEMAIL, array("user" => $Acct, "timeExpires" => time() + 259200, "data" => json_encode(array("uemail" => $cj->email)))));
            $mailer = new HotCRPMailer($Acct, null, $rest);
            $prep = $mailer->make_preparation("@changeemail", $rest);
            if ($prep->sendable) {
                Mailer::send_preparation($prep);
                $Conf->warnMsg("Mail has been sent to " . htmlspecialchars($cj->email) . ". Use the link it contains to confirm your email change request.");
            } else {
                Conf::msg_error("Mail cannot be sent to " . htmlspecialchars($cj->email) . " at this time. Your email address was unchanged.");
            }
            // Save changes *except* for new email, by restoring old email.
            $cj->email = $Acct->email;
            $Acct->preferredEmail = $old_preferredEmail;
        }
    }
    // save account
    return $user_status->save($cj, $Acct, $Me);
}
 static function watch_callback($prow, $minic)
 {
     $ctype = self::$watching->commentType;
     if ($ctype & COMMENTTYPE_RESPONSE && $ctype & COMMENTTYPE_DRAFT) {
         $tmpl = "@responsedraftnotify";
     } else {
         if ($ctype & COMMENTTYPE_RESPONSE) {
             $tmpl = "@responsenotify";
         } else {
             $tmpl = "@commentnotify";
         }
     }
     if ($minic->can_view_comment($prow, self::$watching, false) && ($tmpl !== "@responsedraftnotify" || $minic->act_author_view($prow))) {
         HotCRPMailer::send_to($minic, $tmpl, $prow, array("comment_row" => self::$watching));
     }
 }
Example #11
0
 function save_review($req, $rrow, $prow, $contact, &$tf = null)
 {
     global $Conf, $Opt;
     $newsubmit = @$req["ready"] && !@$req["unready"] && (!$rrow || !$rrow->reviewSubmitted);
     $submit = $newsubmit || $rrow && $rrow->reviewSubmitted;
     $admin = $contact->allow_administer($prow);
     if (!$contact->timeReview($prow, $rrow) && (!isset($req['override']) || !$admin)) {
         return Conf::msg_error("The <a href='" . hoturl("deadlines") . "'>deadline</a> for entering this review has passed." . ($admin ? "  Select the “Override deadlines” checkbox and try again if you really want to override the deadline." : ""));
     }
     $q = array();
     $diff_view_score = VIEWSCORE_FALSE;
     $wc = 0;
     foreach ($this->forder as $field => $f) {
         if (isset($req[$field]) && (!$f->round_mask || $f->is_round_visible($rrow))) {
             $fval = $req[$field];
             if ($f->has_options) {
                 if ($f->parse_is_empty($fval)) {
                     $fval = 0;
                 } else {
                     if (!($fval = $f->parse_value($fval, false))) {
                         continue;
                     }
                 }
             } else {
                 $fval = rtrim($fval);
                 if ($fval != "") {
                     $fval .= "\n";
                 }
                 // Check for valid UTF-8; re-encode from Windows-1252 or Mac OS
                 $fval = convert_to_utf8($fval);
                 if ($f->include_word_count()) {
                     $wc += count_words($fval);
                 }
             }
             if ($rrow && strcmp($rrow->{$field}, $fval) != 0 && strcmp(cleannl($rrow->{$field}), cleannl($fval)) != 0) {
                 $diff_view_score = max($diff_view_score, $f->view_score);
             }
             $q[] = "{$field}='" . sqlq($fval) . "'";
         }
     }
     // get the current time
     $now = time();
     if ($rrow && $rrow->reviewModified && $rrow->reviewModified > $now) {
         $now = $rrow->reviewModified + 1;
     }
     // potentially assign review ordinal (requires table locking since
     // mySQL is stupid)
     $locked = false;
     if ($newsubmit) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_AUTHOR);
         $q[] = "reviewSubmitted={$now}, reviewNeedsSubmit=0";
         if (!$rrow || !$rrow->reviewOrdinal) {
             $result = $Conf->qe("lock tables PaperReview write");
             if (!$result) {
                 return $result;
             }
             $locked = true;
             $result = $Conf->qe("select coalesce(max(reviewOrdinal), 0) from PaperReview where paperId={$prow->paperId} group by paperId");
             if ($result) {
                 $crow = edb_row($result);
                 $q[] = "reviewOrdinal=coalesce(reviewOrdinal, " . ($crow[0] + 1) . ")";
             }
             Dbl::free($result);
             $q[] = "timeDisplayed={$now}";
         }
     }
     // check whether used a review token
     $usedReviewToken = $contact->review_token_cid($prow, $rrow);
     // blind? reviewer type? edit version?
     $reviewBlind = $Conf->is_review_blind(!!@$req["blind"]);
     if ($rrow && $reviewBlind != $rrow->reviewBlind) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_ADMINONLY);
     }
     $q[] = "reviewBlind=" . ($reviewBlind ? 1 : 0);
     if ($rrow && $rrow->reviewType == REVIEW_EXTERNAL && $contact->contactId == $rrow->contactId && $contact->isPC && !$usedReviewToken) {
         $q[] = "reviewType=" . REVIEW_PC;
     }
     if ($rrow && $diff_view_score > VIEWSCORE_FALSE && isset($req["version"]) && ctype_digit($req["version"]) && $req["version"] > defval($rrow, "reviewEditVersion")) {
         $q[] = "reviewEditVersion=" . ($req["version"] + 0);
     }
     if ($diff_view_score > VIEWSCORE_FALSE && $Conf->sversion >= 98) {
         $q[] = "reviewWordCount=" . $wc;
     }
     if (isset($req["reviewFormat"]) && $Conf->sversion >= 104 && @$Opt["formatInfo"]) {
         $fmt = null;
         foreach ($Opt["formatInfo"] as $k => $f) {
             if (@$f["name"] && strcasecmp($f["name"], $req["reviewFormat"]) == 0) {
                 $fmt = (int) $k;
             }
         }
         if (!$fmt && $req["reviewFormat"] && preg_match('/\\A(?:plain\\s*)?(?:text)?\\z/i', $f["reviewFormat"])) {
             $fmt = 0;
         }
         $q[] = "reviewFormat=" . ($fmt === null ? "null" : $fmt);
     }
     // notification
     $notification_bound = $now - 10800;
     $notify = $notify_author = false;
     if (!$rrow || $diff_view_score > VIEWSCORE_FALSE) {
         $q[] = "reviewModified=" . $now;
         // do not notify on updates within 3 hours
         if ($submit && $diff_view_score > VIEWSCORE_ADMINONLY) {
             if (!$rrow || !$rrow->reviewNotified || $rrow->reviewNotified < $notification_bound) {
                 $q[] = $notify = "reviewNotified=" . $now;
             }
             if ((!$rrow || !$rrow->reviewAuthorNotified || $rrow->reviewAuthorNotified < $notification_bound) && $diff_view_score >= VIEWSCORE_AUTHOR && Contact::can_some_author_view_submitted_review($prow)) {
                 $q[] = $notify_author = "reviewAuthorNotified=" . $now;
             }
         }
     }
     // actually affect database
     if ($rrow) {
         $result = $Conf->qe("update PaperReview set " . join(", ", $q) . " where reviewId={$rrow->reviewId}");
         $reviewId = $rrow->reviewId;
         $contactId = $rrow->contactId;
     } else {
         $result = Dbl::qe_raw("insert into PaperReview set paperId={$prow->paperId}, contactId={$contact->contactId}, reviewType=" . REVIEW_PC . ", requestedBy={$contact->contactId}, reviewRound=" . $Conf->current_round() . ", " . join(", ", $q));
         $reviewId = $result ? $result->insert_id : null;
         $contactId = $contact->contactId;
     }
     // unlock tables even if problem
     if ($locked) {
         $Conf->qe("unlock tables");
     }
     if (!$result) {
         return $result;
     }
     // update caches
     Contact::update_rights();
     // look up review ID
     if (!$reviewId) {
         return $reviewId;
     }
     $req['reviewId'] = $reviewId;
     // log updates -- but not if review token is used
     if (!$usedReviewToken && $diff_view_score > VIEWSCORE_FALSE) {
         $text = "Review {$reviewId} ";
         if ($rrow && $contact->contactId != $rrow->contactId) {
             $text .= "by {$rrow->email} ";
         }
         $text .= $newsubmit ? "submitted" : ($submit ? "updated" : "saved draft");
         $contact->log_activity($text, $prow);
     }
     // potentially email chair, reviewers, and authors
     if ($submit) {
         $rrow = $Conf->reviewRow(["reviewId" => $reviewId]);
     }
     if ($submit && ($notify || $notify_author) && $rrow) {
         $tmpl = $newsubmit ? "@reviewsubmit" : "@reviewupdate";
         $submitter = $contact;
         if ($contactId != $submitter->contactId) {
             $submitter = Contact::find_by_id($contactId);
         }
         // construct mail
         $this->mailer_info = array("template" => $tmpl, "rrow" => $rrow, "reviewer_contact" => $submitter, "reviewNumber" => $prow->paperId . unparseReviewOrdinal($rrow->reviewOrdinal), "check_function" => "HotCRPMailer::check_can_view_review", "diff_view_score" => $diff_view_score);
         $this->mailer_preps = array();
         if ($Conf->timeEmailChairAboutReview()) {
             HotCRPMailer::send_manager($tmpl, $prow, $this->mailer_info);
         }
         $prow->notify(WATCHTYPE_REVIEW, array($this, "review_watch_callback"), $contact);
         if (count($this->mailer_preps)) {
             HotCRPMailer::send_combined_preparations($this->mailer_preps);
         }
         unset($this->mailer_info, $this->mailer_preps);
     }
     // if external, forgive the requestor from finishing their review
     if ($rrow && $rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy && $submit) {
         $Conf->q("update PaperReview set reviewNeedsSubmit=0 where paperId={$prow->paperId} and contactId={$rrow->requestedBy} and reviewType=" . REVIEW_SECONDARY . " and reviewSubmitted is null");
     }
     if ($tf !== null) {
         $what = "#{$prow->paperId}" . ($rrow && $rrow->reviewSubmitted ? unparseReviewOrdinal($rrow->reviewOrdinal) : "");
         if ($newsubmit) {
             $tf["newlySubmitted"][] = $what;
         } else {
             if ($diff_view_score > VIEWSCORE_FALSE && $submit) {
                 $tf["updated"][] = $what;
             } else {
                 if ($diff_view_score > VIEWSCORE_FALSE) {
                     $tf["savedDraft"][] = $what;
                 } else {
                     $tf["unchanged"][] = $what;
                 }
             }
         }
         if ($notify_author) {
             $tf["authorNotified"][] = $what;
         }
     }
     return $result;
 }
Example #12
0
function refuseReview()
{
    global $Conf, $Opt, $Me, $prow, $paperTable;
    Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write");
    $rrow = $paperTable->editrrow;
    $hadToken = defval($rrow, "reviewToken", 0) != 0;
    $result = Dbl::qe("delete from PaperReview where reviewId={$rrow->reviewId}");
    if (!$result) {
        return;
    }
    $reason = defval($_REQUEST, "reason", "");
    if ($reason == "Optional explanation") {
        $reason = "";
    }
    $result = Dbl::qe("insert into PaperReviewRefused set paperId={$rrow->paperId}, contactId={$rrow->contactId}, requestedBy={$rrow->requestedBy}, reason=?", trim($reason));
    if (!$result) {
        return;
    }
    // now the requester must potentially complete their review
    if ($rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy > 0) {
        Contact::update_review_delegation($rrow->paperId, $rrow->requestedBy, -1);
    }
    Dbl::qe_raw("unlock tables");
    // send confirmation email
    $Requester = Contact::find_by_id($rrow->requestedBy);
    $reqprow = $Conf->paperRow($prow->paperId, $rrow->requestedBy);
    HotCRPMailer::send_to($Requester, "@refusereviewrequest", $reqprow, array("reviewer_contact" => $rrow, "reason" => $reason));
    // confirmation message
    $Conf->confirmMsg("The request that you review paper #{$prow->paperId} has been removed.  Mail was sent to the person who originally requested the review.");
    if ($hadToken) {
        $Conf->update_rev_tokens_setting(true);
    }
    $prow = null;
    confHeader();
    $Conf->footer();
    exit;
}
 static function prepare_to($recipient, $template, $row, $rest = array())
 {
     if (defval($recipient, "disabled")) {
         return null;
     }
     $mailer = new HotCRPMailer($recipient, $row, $rest);
     if (($checkf = get($rest, "check_function")) && !call_user_func($checkf, $recipient, $mailer->row, $mailer->rrow)) {
         return null;
     }
     return $mailer->make_preparation($template, $rest);
 }