private function run() { global $Conf, $Opt, $Me, $Error, $subjectPrefix, $mailer_options; $subject = trim(defval($_REQUEST, "subject", "")); if (substr($subject, 0, strlen($subjectPrefix)) != $subjectPrefix) { $subject = $subjectPrefix . $subject; } $emailBody = $_REQUEST["emailBody"]; $template = array("subject" => $subject, "body" => $emailBody); $rest = array("cc" => $_REQUEST["cc"], "reply-to" => $_REQUEST["replyto"], "no_error_quit" => true); $rest = array_merge($rest, $mailer_options); // test whether this mail is paper-sensitive $mailer = new HotCRPMailer($Me, null, $rest); $prep = $mailer->make_preparation($template, $rest); $paper_sensitive = preg_match('/%[A-Z0-9]+[(%]/', $prep->subject . $prep->body); $q = $this->recip->query($paper_sensitive); if (!$q) { return Conf::msg_error("Bad recipients value"); } $result = $Conf->qe($q); if (!$result) { return; } $recipients = defval($_REQUEST, "recipients", ""); if ($this->sending) { $q = "recipients='" . sqlq($recipients) . "', cc='" . sqlq($_REQUEST["cc"]) . "', replyto='" . sqlq($_REQUEST["replyto"]) . "', subject='" . sqlq($_REQUEST["subject"]) . "', emailBody='" . sqlq($_REQUEST["emailBody"]) . "'"; if ($Conf->sversion >= 79) { $q .= ", q='" . sqlq($_REQUEST["q"]) . "', t='" . sqlq($_REQUEST["t"]) . "'"; } if ($log_result = Dbl::query_raw("insert into MailLog set {$q}")) { $this->mailid_text = " #" . $log_result->insert_id; } $Me->log_activity("Sending mail{$this->mailid_text} \"{$subject}\""); } else { $rest["no_send"] = true; } $mailer = new HotCRPMailer(); $mailer->combination_type = $this->recip->combination_type($paper_sensitive); $fake_prep = new HotCRPMailPreparation(); $fake_prep->fake = true; $last_prep = $fake_prep; $nrows_done = 0; $nrows_left = edb_nrows($result); $nwarnings = 0; $preperrors = array(); $revinform = $recipients == "newpcrev" ? array() : null; while ($row = PaperInfo::fetch($result, $Me)) { ++$nrows_done; $contact = new Contact($row); $rest["newrev_since"] = $this->recip->newrev_since; $mailer->reset($contact, $row, $rest); $prep = $mailer->make_preparation($template, $rest); if ($prep->errors) { foreach ($prep->errors as $lcfield => $hline) { $reqfield = $lcfield == "reply-to" ? "replyto" : $lcfield; $Error[$reqfield] = true; $emsg = Mailer::$email_fields[$lcfield] . " destination isn’t a valid email list: <blockquote><tt>" . htmlspecialchars($hline) . "</tt></blockquote> Make sure email address are separated by commas; put names in \"quotes\" and email addresses in <angle brackets>."; if (!isset($preperrors[$emsg])) { Conf::msg_error($emsg); } $preperrors[$emsg] = true; } } else { if ($this->process_prep($prep, $last_prep, $row)) { if ((!$Me->privChair || @$Opt["chairHidePasswords"]) && !@$last_prep->sensitive) { $srest = array_merge($rest, array("sensitivity" => "display")); $mailer->reset($contact, $row, $srest); $last_prep->sensitive = $mailer->make_preparation($template, $srest); } } } if ($nwarnings != $mailer->nwarnings() || $nrows_done % 5 == 0) { $this->echo_mailinfo($nrows_done, $nrows_left); } if ($nwarnings != $mailer->nwarnings()) { $this->echo_prologue(); $nwarnings = $mailer->nwarnings(); echo "<div id='foldmailwarn{$nwarnings}' class='hidden'><div class='warning'>", join("<br />", $mailer->warnings()), "</div></div>"; $Conf->echoScript("\$\$('mailwarnings').innerHTML = \$\$('foldmailwarn{$nwarnings}').innerHTML;"); } if ($this->sending && $revinform !== null) { $revinform[] = "(paperId={$row->paperId} and contactId={$row->contactId})"; } } $this->process_prep($fake_prep, $last_prep, (object) array("paperId" => -1)); $this->echo_mailinfo($nrows_done, $nrows_left); if (!$this->started && !count($preperrors)) { return Conf::msg_error("No users match “" . $this->recip->unparse() . "” for that search."); } else { if (!$this->started) { return false; } else { if (!$this->sending) { $this->echo_actions(); } } } if ($revinform) { $Conf->qe("update PaperReview set timeRequestNotified=" . time() . " where " . join(" or ", $revinform)); } echo "</div></form>"; $Conf->echoScript("fold('mail', null);"); $Conf->footer(); exit; }
function 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); } }
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)); } }
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; }
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); }