function initialize_user() { global $Conf, $Opt, $Me; // backwards compat: set $_SESSION["user"] from $_SESSION["Me"] if (!isset($_SESSION["user"]) && isset($_SESSION["Me"])) { $x = $_SESSION["Me"]; $_SESSION["user"] = "******"; unset($_SESSION["Me"], $_SESSION["pcmembers"]); } if (!isset($_SESSION["trueuser"]) && isset($_SESSION["user"])) { $_SESSION["trueuser"] = $_SESSION["user"]; } if (is_string(@$_SESSION["trueuser"])) { $userwords = explode(" ", $_SESSION["trueuser"]); $_SESSION["trueuser"] = (object) array("contactId" => $userwords[0], "dsn" => $userwords[1], "email" => @$userwords[2]); } // load current user $Me = null; $trueuser = @$_SESSION["trueuser"]; if ($trueuser && $trueuser->dsn == $Conf->dsn) { $Me = Contact::find_by_id($trueuser->contactId); } if (!$Me && $trueuser && $trueuser->email) { $Me = Contact::find_by_email($trueuser->email); } if (!$Me) { $Me = new Contact($trueuser); } $Me = $Me->activate(); // if bounced through login, add post data if (isset($_SESSION["login_bounce"]) && !$Me->is_empty()) { $lb = $_SESSION["login_bounce"]; if ($lb[0] == $Conf->dsn && $lb[2] !== "index" && $lb[2] == Navigation::page()) { foreach ($lb[3] as $k => $v) { if (!isset($_REQUEST[$k])) { $_REQUEST[$k] = $_GET[$k] = $v; } } $_REQUEST["after_login"] = 1; } unset($_SESSION["login_bounce"]); } }
public function mail() { if (!(($id = OAInput::post('id')) && ($contact = Contact::find_by_id($id, array('select' => 'name, email, message'))))) { return false; } if (!(($admin_ids = array_unique(column_array(UserRole::find('all', array('select' => 'user_id', 'conditions' => array('name IN (?)', array('root', 'contact_manager')))), 'user_id'))) && ($admins = User::find('all', array('select' => 'name, email', 'conditions' => array('id IN (?)', $admin_ids)))))) { return false; } $this->load->library('OAMail'); $email = $contact->email; $name = $contact->name; $message = $contact->message; $mail = OAMail::create()->setSubject('[系統通知] 官網有新的留言!')->setBody("<article style='font-size:15px;line-height:22px;color:rgb(85,85,85)'><p style='margin-bottom:0'>Hi 管理員,</p><section style='padding:5px 20px'><p>剛剛有一個訪客在您的「聯絡我們」留言囉,以下他所留下的聯絡資料:</p><table style='width:100%;border-collapse:collapse'><tbody><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>E-Mail:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $email . "</td></tr><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>稱 呼:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $name . "</td></tr><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>內容:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $message . "</td></tr></tbody></table><br/><p style='text-align:right'>如果需要詳細列表,可以置<a href='" . base_url('admin', 'contacts') . "' style='color:rgba(96,156,255,1);margin:0 2px'>管理後台</a>檢閱。</p></section></article>"); foreach ($admins as $admin) { $mail->addTo($admin->email, $admin->name); } $mail->send(); $mail = OAMail::create()->setSubject('[宙思設計] 留言成功通知!')->setBody("<article style='font-size:15px;line-height:22px;color:rgb(85, 85, 85)'><p style='margin-bottom:0'>Hi " . $name . ",</p><section style='padding:5px 20px'><p>您好,我們是<a href='http://www.zeusdesign.com.tw/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計</a>團隊,我們已經收到您的留言囉。</p><p>我們稍後會有專人主動與您聯絡或回信給您!</p><p>若是尚未得到回覆,您可以至<a href='https://www.facebook.com/ZeusDesignStudio/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計臉書粉絲專頁</a>留言,或來電(02-2941-6737)聯絡我們。</p><p style='text-align:right'>- <a href='http://www.zeusdesign.com.tw/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計</a>團隊感謝您。</p></section></article>")->addTo($email, $name); $mail->send(); }
function run(Contact $user, $qreq, $ssel) { global $Conf, $Opt; // maybe download preferences for someone else $Rev = $user; if (($cid = cvtint($qreq->reviewer)) > 0 && $user->privChair) { if (!($Rev = Contact::find_by_id($cid))) { return Conf::msg_error("No such reviewer"); } } if (!$Rev->isPC) { return self::EPERM; } $q = $Conf->paperQuery($Rev, array("paperId" => $ssel->selection(), "topics" => 1, "reviewerPreference" => 1)); $result = Dbl::qe_raw($q); $texts = array(); while ($prow = PaperInfo::fetch($result, $Rev)) { $t = $prow->paperId . "," . CsvGenerator::quote($prow->title); if ($prow->conflictType > 0) { $t .= ",conflict"; } else { $t .= "," . unparse_preference($prow); } $t .= "\n"; if ($this->extended) { if ($Rev->can_view_authors($prow, false)) { $t .= prefix_word_wrap("# Authors: ", $prow->pretty_text_author_list(), "# "); } $t .= prefix_word_wrap("# Abstract: ", rtrim($prow->abstract), "# "); if ($prow->topicIds != "") { $t .= prefix_word_wrap("# Topics: ", $prow->unparse_topics_text(), "# "); } $t .= "\n"; } defappend($texts[$prow->paperId], $t); } downloadCSV(join("", $ssel->reorder($texts)), ["paper", "title", "preference"], "revprefs"); }
public function is_replied($id = 0) { if (!($id && ($contact = Contact::find_by_id($id, array('select' => 'id, is_replied, updated_at'))))) { return $this->output_json(array('status' => false, 'message' => '當案不存在,或者您的權限不夠喔!')); } $posts = OAInput::post(); if ($msg = $this->_validation_is_replied_posts($posts)) { return $this->output_json(array('status' => false, 'message' => $msg, 'content' => Contact::$replyNames[$contact->is_replied])); } if ($columns = array_intersect_key($posts, $contact->table()->columns)) { foreach ($columns as $column => $value) { $contact->{$column} = $value; } } $update = Contact::transaction(function () use($contact) { return $contact->save(); }); if ($update) { return $this->output_json(array('status' => true, 'message' => '更新成功!', 'content' => Contact::$replyNames[$contact->is_replied])); } else { return $this->output_json(array('status' => false, 'message' => '更新失敗!', 'content' => Contact::$replyNames[$contact->is_replied])); } }
function change_email_by_capability() { global $Conf, $Me; $capmgr = $Conf->capability_manager(); $capdata = $capmgr->check($_REQUEST["changeemail"]); if (!$capdata || $capdata->capabilityType != CAPTYPE_CHANGEEMAIL || !($capdata->data = json_decode($capdata->data)) || !@$capdata->data->uemail) { error_go(false, "That email change code has expired, or you didn’t enter it correctly."); } $Acct = Contact::find_by_id($capdata->contactId); if (!$Acct) { error_go(false, "No such account."); } $email = $capdata->data->uemail; if (Contact::id_by_email($email)) { error_go(false, "Email address “" . htmlspecialchars($email) . "” is already in use. You may want to <a href=\"" . hoturl("mergeaccounts") . "\">merge these accounts</a>."); } $Acct->change_email($email); $capmgr->delete($capdata); $Conf->confirmMsg("Your email address has been changed."); if (!$Me->has_database_account() || $Me->contactId == $Acct->contactId) { $Me = $Acct->activate(); } }
if ($resetcap === null && preg_match(',\\A/(U?1[-\\w]+)(?:/|\\z),i', Navigation::path(), $m)) { $resetcap = $m[1]; } if (!$resetcap) { error_go(false, "You didn’t enter the full password reset link into your browser. Make sure you include the reset code (the string of letters, numbers, and other characters at the end)."); } $iscdb = substr($resetcap, 0, 1) === "U"; $capmgr = $Conf->capability_manager($resetcap); $capdata = $capmgr->check($resetcap); if (!$capdata || $capdata->capabilityType != CAPTYPE_RESETPASSWORD) { error_go(false, "That password reset code has expired, or you didn’t enter it correctly."); } if ($iscdb) { $Acct = Contact::contactdb_find_by_id($capdata->contactId); } else { $Acct = Contact::find_by_id($capdata->contactId); } if (!$Acct) { error_go(false, "That password reset code refers to a user who no longer exists. Either create a new account or contact the conference administrator."); } // don't show information about the current user, if there is one $Me = new Contact(); $password_class = ""; if (isset($_POST["go"]) && check_post()) { $_POST["password"] = trim(get_s($_POST, "password")); $_POST["password2"] = trim(get_s($_POST, "password2")); if ($_POST["password"] == "") { Conf::msg_error("You must enter a password."); } else { if ($_POST["password"] !== $_POST["password2"]) { Conf::msg_error("The two passwords you entered did not match.");
function __construct($search, $args = array(), $qreq = null) { global $Conf; $this->search = $search; $this->contact = $this->search->contact; $this->qreq = $qreq ?: new Qobject(); $this->sortable = isset($args["sort"]) && $args["sort"]; if ($this->sortable && is_string($args["sort"])) { $this->sorters[] = ListSorter::parse_sorter($args["sort"]); } else { if ($this->sortable && $this->qreq->sort) { $this->sorters[] = ListSorter::parse_sorter($this->qreq->sort); } else { $this->sorters[] = ListSorter::parse_sorter(""); } } $this->foldable = $this->sortable || !!get($args, "foldable") || $this->contact->privChair; $this->_paper_link_page = ""; if (isset($qreq->linkto) && ($qreq->linkto == "paper" || $qreq->linkto == "review" || $qreq->linkto == "assign")) { $this->_paper_link_page = $qreq->linkto; } $this->listNumber = 0; if (get($args, "list")) { $this->listNumber = SessionList::allocate($search->listId($this->sortdef())); } if (is_string(get($args, "display"))) { $this->display = " " . $args["display"] . " "; } else { $svar = get($args, "foldtype", "pl") . "display"; $this->display = $Conf->session($svar, ""); } if (isset($args["reviewer"]) && ($r = $args["reviewer"])) { if (!is_object($r)) { error_log(caller_landmark() . ": warning: 'reviewer' not an object"); $r = Contact::find_by_id($r); } $this->_reviewer = $r; } $this->atab = $this->qreq->atab; $this->_row_id_pattern = get($args, "row_id_pattern"); $this->tagger = new Tagger($this->contact); $this->scoresOk = $this->contact->privChair || $this->contact->is_reviewer() || $Conf->timeAuthorViewReviews(); $this->qopts = array("scores" => [], "options" => true); if ($this->search->complexSearch($this->qopts)) { $this->qopts["paperId"] = $this->search->paperList(); } // NB that actually processed the search, setting PaperSearch::viewmap $this->viewmap = new Qobject($this->search->viewmap); if ($this->viewmap->compact || $this->viewmap->cc || $this->viewmap->compactcolumn || $this->viewmap->ccol || $this->viewmap->compactcolumns) { $this->viewmap->compactcolumns = $this->viewmap->columns = true; } if ($this->viewmap->column || $this->viewmap->col) { $this->viewmap->columns = true; } if ($this->viewmap->stat || $this->viewmap->stats || $this->viewmap->totals) { $this->viewmap->statistics = true; } if ($this->viewmap->authors && $this->viewmap->au === null) { $this->viewmap->au = true; } if ($Conf->submission_blindness() != Conf::BLIND_OPTIONAL && $this->viewmap->au && $this->viewmap->anonau === null) { $this->viewmap->anonau = true; } if ($this->viewmap->anonau && $this->viewmap->au === null) { $this->viewmap->au = true; } if ($this->viewmap->rownumbers) { $this->viewmap->rownum = true; } }
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; }
} loadRows(); } } } } } // deny review request if (isset($_REQUEST["deny"]) && $Me->allow_administer($prow) && check_post() && ($email = trim(defval($_REQUEST, "email", "")))) { Dbl::qe_raw("lock tables ReviewRequest write, ContactInfo read, PaperConflict read, PaperReview read, PaperReviewRefused write"); // Need to be careful and not expose inappropriate information: // this email comes from the chair, who can see all, but goes to a PC // member, who can see less. $result = Dbl::qe_raw("select requestedBy from ReviewRequest where paperId={$prow->paperId} and email='" . sqlq($email) . "'"); if ($row = edb_row($result)) { $Requester = Contact::find_by_id($row[0]); Dbl::qe_raw("delete from ReviewRequest where paperId={$prow->paperId} and email='" . sqlq($email) . "'"); if (($reqId = Contact::id_by_email($email)) > 0) { Dbl::qe_raw("insert into PaperReviewRefused (paperId, contactId, requestedBy, reason) values ({$prow->paperId}, {$reqId}, {$Requester->contactId}, 'request denied by chair')"); } // send anticonfirmation email HotCRPMailer::send_to($Requester, "@denyreviewrequest", $prow, array("reviewer_contact" => (object) array("fullName" => trim(defval($_REQUEST, "name", "")), "email" => $email))); $Conf->confirmMsg("Proposed reviewer denied."); } else { Conf::msg_error("No one has proposed that " . htmlspecialchars($email) . " review this paper."); } Dbl::qx_raw("unlock tables"); unset($_REQUEST["email"], $_GET["email"], $_POST["email"]); unset($_REQUEST["name"], $_GET["name"], $_POST["name"]); } // add primary or secondary reviewer
function ksort_cid_array(&$a) { $pcm = pcMembers(); uksort($a, function ($a, $b) use($pcm) { if (isset($pcm[$a]) && isset($pcm[$b])) { return $pcm[$a]->sort_position - $pcm[$b]->sort_position; } if (isset($pcm[$a])) { $as = $pcm[$a]->sorter; } else { if (isset($this->contact_sorter_map_[$a])) { $as = $this->contact_sorter_map_[$a]; } else { $x = Contact::find_by_id($a); $as = $this->contact_sorter_map_[$a] = $x->sorter; } } if (isset($pcm[$b])) { $bs = $pcm[$b]->sorter; } else { if (isset($this->contact_sorter_map_[$b])) { $bs = $this->contact_sorter_map_[$b]; } else { $x = Contact::find_by_id($b); $bs = $this->contact_sorter_map_[$b] = $x->sorter; } } return strcasecmp($as, $bs); }); }
exit($status); } if (!@$Opt["contactdb_dsn"]) { fwrite(STDERR, "Conference has no contactdb_dsn\n"); exit(1); } $users = isset($arg["u"]) || isset($arg["users"]); $papers = isset($arg["p"]) || isset($arg["papers"]); $collaborators = isset($arg["collaborators"]); if (!$users && !$papers && !$collaborators) { $users = $papers = true; } if ($users) { $result = Dbl::ql($Conf->dblink, "select ContactInfo.contactId, email from ContactInfo\n left join PaperConflict on (PaperConflict.contactId=ContactInfo.contactId and PaperConflict.conflictType>=" . CONFLICT_AUTHOR . ")\n left join PaperReview on (PaperReview.contactId=ContactInfo.contactId)\n where roles!=0 or PaperConflict.conflictType is not null\n or PaperReview.reviewId is not null\n group by ContactInfo.contactId"); while ($row = edb_row($result)) { $contact = Contact::find_by_id($row[0]); $contact->contactdb_update(); } Dbl::free($result); } if ($papers) { $result = Dbl::ql(Contact::contactdb(), "select confid from Conferences where `dbname`=?", $Opt["dbName"]); $row = Dbl::fetch_first_row($result); if (!$row) { fwrite(STDERR, "Conference is not recored in contactdb\n"); exit(1); } $confid = $row[0]; $result = Dbl::ql($Conf->dblink, "select paperId, title from Paper"); $q = array(); while ($row = edb_row($result)) {
function save($cj, $old_user = null, $actor = null) { global $Conf, $Me, $Now; assert(is_object($cj)); self::normalize_name($cj); if (!$old_user && is_int(get($cj, "id")) && $cj->id) { $old_user = Contact::find_by_id($cj->id); } else { if (!$old_user && is_string(get($cj, "email")) && $cj->email) { $old_user = Contact::find_by_email($cj->email); } } if (!get($cj, "id")) { $cj->id = $old_user ? $old_user->contactId : "new"; } if ($cj->id !== "new" && $old_user && $cj->id != $old_user->contactId) { $this->set_error("id", "Saving user with different ID"); return false; } $no_old_db_account = !$old_user || !$old_user->has_database_account(); $old_cdb_user = null; if ($old_user && $old_user->has_email()) { $old_cdb_user = Contact::contactdb_find_by_email($old_user->email); } else { if (is_string(get($cj, "email")) && $cj->email) { $old_cdb_user = Contact::contactdb_find_by_email($cj->email); } } $user = $old_user ?: $old_cdb_user; $this->normalize($cj, $user); if ($this->nerrors) { return false; } $this->check_invariants($cj); $user = $user ?: new Contact(); if (($send = $this->send_email) === null) { $send = !$old_cdb_user; } if ($user->save_json($cj, $actor, $send)) { return $user; } else { return false; } }
function save_comment($text, $is_response, $roundnum) { global $Me, $Conf, $prow, $crow; if ($crow) { $roundnum = (int) $crow->commentRound; } // If I have a review token for this paper, save under that anonymous user. $user = $Me; if ((!$crow || $crow->contactId != $Me->contactId) && ($cid = $Me->review_token_cid($prow)) && (!$crow || $crow->contactId == $cid)) { $user = Contact::find_by_id($cid); } $req = array("visibility" => @$_REQUEST["visibility"], "submit" => $is_response && @$_REQUEST["submitresponse"], "text" => $text, "tags" => @$_REQUEST["commenttags"], "blind" => @$_REQUEST["blind"]); if ($is_response && !$crow) { $cinfo = new CommentInfo((object) array("commentType" => COMMENTTYPE_RESPONSE, "commentRound" => $roundnum), $prow); } else { $cinfo = new CommentInfo($crow, $prow); } $ok = $cinfo->save($req, $user); $what = $is_response ? "Response" : "Comment"; $confirm = false; if (!$ok && $is_response) { $crows = $Conf->comment_rows($Conf->comment_query("paperId={$prow->paperId} and (commentType&" . COMMENTTYPE_RESPONSE . ")!=0 and commentRound={$roundnum}"), $Me); reset($crows); $cur_response = @current($crows); if ($cur_response && $cur_response->comment == $text) { $cinfo = new CommentInfo($cur_response, $prow); $ok = true; } else { $confirm = Ht::xmsg("error", "A response was entered concurrently by another user. Reload to see it."); } } if (!$ok) { /* nada */ } else { if ($is_response && (!$cinfo->commentId || $cinfo->commentType & COMMENTTYPE_DRAFT)) { if ($cinfo->commentId) { $confirm = 'Response saved. <strong>This draft response will not be shown to reviewers.</strong>'; } else { $confirm = 'Response deleted.'; } $isuf = $roundnum ? "_{$roundnum}" : ""; if (($dl = $Conf->printableTimeSetting("resp_done{$isuf}")) != "N/A") { $confirm .= " You have until {$dl} to submit the response."; } $confirm = Ht::xmsg("warning", $confirm); } else { if ($is_response) { $rname = $Conf->resp_round_text($roundnum); $confirm = Ht::xmsg("confirm", ($rname ? "{$rname} response" : "Response") . ' submitted.'); } else { if ($cinfo->commentId) { $confirm = Ht::xmsg("confirm", "Comment saved."); } else { $confirm = Ht::xmsg("confirm", "Comment deleted."); } } } } $j = array("ok" => $ok); if ($cinfo->commentId) { $j["cmt"] = $cinfo->unparse_json($Me); } if ($confirm) { $j["msg"] = $confirm; } $Conf->ajaxExit($j); }
static function send_manager($template, $row, $rest = array()) { if ($row && $row->managerContactId && ($c = Contact::find_by_id($row->managerContactId))) { self::send_to($c, $template, $row, $rest); } else { self::send_to(Contact::site_contact(), $template, $row, $rest); } }
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); } }
function update_schema_transfer_address($Conf) { $result = Dbl::ql("select * from ContactAddress"); while ($row = edb_orow($result)) { if ($c = Contact::find_by_id($row->contactId)) { $x = (object) array(); if ($row->addressLine1 || $row->addressLine2) { $x->address = array(); } foreach (array("addressLine1", "addressLine2") as $k) { if ($row->{$k}) { $x->address[] = $row->{$k}; } } foreach (array("city" => "city", "state" => "state", "zipCode" => "zip", "country" => "country") as $k => $v) { if ($row->{$k}) { $x->{$v} = $row->{$k}; } } $c->merge_and_save_data($x); } } return true; }
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 reviewer() { if (is_object($this->_reviewer)) { return $this->_reviewer; } else { if ($this->_reviewer) { return Contact::find_by_id($this->_reviewer); } else { return null; } } }