function save_review($pid, $contact, $revreq) { $pid = is_object($pid) ? $pid->paperId : $pid; $rf = ReviewForm::get(); $rf->save_review($revreq, fetch_review($pid, $contact), fetch_paper($pid, $contact), $contact); return fetch_review($pid, $contact); }
private function _review_word_counts($restriction, $basek, $k, $count) { $a = $this->review_cid_int_array($restriction, $basek, $k); if ($a !== false || $count) { return $a; } $result = Dbl::qe("select * from PaperReview where reviewWordCount is null and paperId={$this->paperId}"); $rf = ReviewForm::get(); $qs = []; while ($rrow = edb_orow($result)) { $qs[] = "update PaperReview set reviewWordCount=" . $rf->word_count($rrow) . " where reviewId=" . $rrow->reviewId; } Dbl::free($result); if (count($qs)) { $mresult = Dbl::multi_qe(join(";", $qs)); while ($result = $mresult->next()) { Dbl::free($result); } unset($this->reviewWordCounts, $this->allReviewWordCounts); } return $this->_review_word_counts($restriction, $basek, $k, $count + 1); }
function reviewTable($prow, $rrows, $crows, $rrow, $mode, $proposals = null) { global $Conf, $Me; $subrev = array(); $nonsubrev = array(); $foundRrow = $foundMyReview = $notShown = 0; $conflictType = $Me->view_conflict_type($prow); $allow_admin = $Me->allow_administer($prow); $admin = $Me->can_administer($prow); $hideUnviewable = $conflictType > 0 && !$admin || !$Me->act_pc($prow) && !$Conf->setting("extrev_view"); $show_colors = $Me->can_view_reviewer_tags($prow); $tagger = $show_colors ? new Tagger($Me) : null; $xsep = ' <span class="barsep">·</span> '; $want_scores = $mode !== "assign" && $mode !== "edit" && $mode !== "re"; $want_requested_by = false; $want_retract = false; $pcm = pcMembers(); $score_header = array(); // actual rows foreach ($rrows as $rr) { $highlight = $rrow && $rr->reviewId == $rrow->reviewId; $foundRrow += $highlight; if ($Me->is_my_review($rr)) { $foundMyReview++; } $canView = $Me->can_view_review($prow, $rr, null); // skip unsubmitted reviews if (!$canView && $hideUnviewable) { if ($rr->reviewNeedsSubmit == 1 && $rr->reviewModified) { $notShown++; } continue; } $t = ""; $tclass = $rrow && $highlight ? "hilite" : ""; // review ID $id = "Review"; if ($rr->reviewSubmitted) { $id .= " #" . $prow->paperId . unparseReviewOrdinal($rr->reviewOrdinal); } else { if ($rr->reviewType == REVIEW_SECONDARY && $rr->reviewNeedsSubmit <= 0) { $id .= " (delegated)"; } else { if ($rr->reviewModified > 0) { $id .= " (in progress)"; } else { $id .= " (not started)"; } } } $rlink = unparseReviewOrdinal($rr); if ($rrow && $rrow->reviewId == $rr->reviewId) { if ($Me->contactId == $rr->contactId && !$rr->reviewSubmitted) { $id = "Your {$id}"; } $t .= '<td><a href="' . hoturl("review", "p={$prow->paperId}&r={$rlink}") . '" class="q"><b>' . $id . '</b></a></td>'; } else { if (!$canView) { $t .= "<td>{$id}</td>"; } else { if ($rrow || $rr->reviewModified <= 0 || ($mode === "re" || $mode === "assign") && $Me->can_review($prow, $rr)) { $t .= '<td><a href="' . hoturl("review", "p={$prow->paperId}&r={$rlink}") . '">' . $id . '</a></td>'; } else { if (Navigation::page() !== "paper") { $t .= '<td><a href="' . hoturl("paper", "p={$prow->paperId}#r{$rlink}") . '">' . $id . '</a></td>'; } else { $t .= '<td><a href="#r' . $rlink . '">' . $id . '</a></td>'; } } } } // primary/secondary glyph if ($conflictType > 0 && !$admin) { $rtype = ""; } else { if ($rr->reviewType > 0) { $rtype = review_type_icon($rr->reviewType); if ($admin && $mode === "assign") { $rtype .= _review_table_round_selector($prow, $rr); } else { if ($rr->reviewRound > 0 && $Me->can_view_review_round($prow, $rr)) { $rtype .= ' <span class="revround" title="Review round">' . htmlspecialchars($Conf->round_name($rr->reviewRound, true)) . "</span>"; } } } else { $rtype = ""; } } // reviewer identity $showtoken = $rr->reviewToken && $Me->can_review($prow, $rr); if (!$Me->can_view_review_identity($prow, $rr, null)) { $t .= $rtype ? "<td>{$rtype}</td>" : '<td class="empty"></td>'; } else { if (!$showtoken || !Contact::is_anonymous_email($rr->email)) { $n = $Me->name_html_for($rr); } else { $n = "[Token " . encode_token((int) $rr->reviewToken) . "]"; } if ($allow_admin) { $n .= _review_table_actas($rr); } $t .= '<td class="rl"><span class="taghl">' . $n . '</span>' . ($rtype ? " {$rtype}" : "") . "</td>"; if ($show_colors && (get($rr, "contactRoles") || get($rr, "contactTags"))) { $tags = Contact::roles_all_contact_tags(get($rr, "contactRoles"), get($rr, "contactTags")); $tags = Tagger::strip_nonviewable($tags, $Me); if ($tags && ($color = TagInfo::color_classes($tags))) { $tclass = $color; } } } // requester if ($mode === "assign") { if (($conflictType <= 0 || $admin) && $rr->reviewType == REVIEW_EXTERNAL && !$showtoken) { $t .= '<td style="font-size:smaller">'; if ($rr->requestedBy == $Me->contactId) { $t .= "you"; } else { if ($u = get($pcm, $rr->requestedBy)) { $t .= $Me->reviewer_html_for($rr->requestedBy); } else { $t .= Text::user_html([$rr->reqFirstName, $rr->reqLastName, $rr->reqEmail]); } } $t .= '</td>'; $want_requested_by = true; } else { $t .= '<td class="empty"></td>'; } } // actions if ($mode === "assign" && ($conflictType <= 0 || $admin) && $rr->reviewType == REVIEW_EXTERNAL && $rr->reviewModified <= 0 && ($rr->requestedBy == $Me->contactId || $admin)) { $t .= '<td>' . _retract_review_request_form($prow, $rr) . '</td>'; } // scores $scores = array(); if ($want_scores && $canView) { $view_score = $Me->view_score_bound($prow, $rr); $rf = ReviewForm::get(); foreach ($rf->forder as $fid => $f) { if (!$f->has_options || $f->view_score <= $view_score || $f->round_mask && !$f->is_round_visible($rr)) { /* do nothing */ } else { if ($rr->{$fid}) { if (!get($score_header, $fid)) { $score_header[$fid] = "<th>" . $f->web_abbreviation() . "</th>"; } $scores[$fid] = '<td class="revscore" data-rf="' . $f->uid . '">' . $f->unparse_value($rr->{$fid}, ReviewField::VALUE_SC) . '</td>'; } else { if (get($score_header, $fid) === null) { $score_header[$fid] = ""; } } } } } // affix if (!$rr->reviewSubmitted) { $nonsubrev[] = array($tclass, $t, $scores); } else { $subrev[] = array($tclass, $t, $scores); } } // proposed review rows if ($proposals) { foreach ($proposals as $rr) { $t = ""; // review ID $t = "<td>Proposed review</td>"; // reviewer identity $t .= "<td>" . Text::user_html($rr); if ($allow_admin) { $t .= _review_table_actas($rr); } $t .= "</td>"; // requester if ($conflictType <= 0 || $admin) { $t .= '<td style="font-size:smaller">'; if ($rr->requestedBy == $Me->contactId) { $t .= "you"; } else { if ($u = get($pcm, $rr->requestedBy)) { $t .= $Me->reviewer_html_for($rr->requestedBy); } else { $t .= Text::user_html([$rr->reqFirstName, $rr->reqLastName, $rr->reqEmail]); } } $t .= '</td>'; $want_requested_by = true; } $t .= '<td>'; if ($admin) { $t .= '<small>' . Ht::form(hoturl_post("assign", "p={$prow->paperId}")) . '<div class="inline">' . Ht::hidden("name", $rr->name) . Ht::hidden("email", $rr->email) . Ht::hidden("reason", $rr->reason); if ($rr->reviewRound !== null) { if ($rr->reviewRound == 0) { $rname = "unnamed"; } else { $rname = $Conf->round_name($rr->reviewRound); } if ($rname) { $t .= Ht::hidden("round", $rname); } } $t .= Ht::submit("add", "Approve review", array("style" => "font-size:smaller")) . ' ' . Ht::submit("deny", "Deny request", array("style" => "font-size:smaller")) . '</div></form>'; } else { if ($rr->reqEmail === $Me->email) { $t .= _retract_review_request_form($prow, $rr); } } $t .= '</td>'; // affix $nonsubrev[] = array("", $t); } } // unfinished review notification $notetxt = ""; if ($conflictType >= CONFLICT_AUTHOR && !$admin && $notShown && $Me->can_view_review($prow, null, null)) { if ($notShown == 1) { $t = "1 review remains outstanding."; } else { $t = "{$notShown} reviews remain outstanding."; } $t .= '<br /><span class="hint">You will be emailed if new reviews are submitted or existing reviews are changed.</span>'; $notetxt = '<div class="revnotes">' . $t . "</div>"; } // completion if (count($nonsubrev) + count($subrev)) { if ($want_requested_by) { array_unshift($score_header, '<th class="revsl">Requester</th>'); } $score_header_text = join("", $score_header); $t = "<table class=\"reviewers"; if ($score_header_text) { $t .= " reviewers_scores"; } if ($list = SessionList::active()) { $t .= " has_hotcrp_list\" data-hotcrp-list=\"" . $list->listno; } $t .= "\">\n"; if ($score_header_text) { $t .= '<tr><td class="empty" colspan="2"></td>' . $score_header_text . "</tr>\n"; } foreach (array_merge($subrev, $nonsubrev) as $r) { $t .= '<tr class="rl' . ($r[0] ? " {$r['0']}" : "") . '">' . $r[1]; if (get($r, 2)) { foreach ($score_header as $fid => $header_needed) { if ($header_needed) { $x = get($r[2], $fid); $t .= $x ?: "<td class=\"revscore rs_{$fid}\"></td>"; } } } else { if (count($score_header)) { $t .= '<td colspan="' . count($score_header) . '"></td>'; } } $t .= "</tr>\n"; } if ($score_header_text) { $Conf->footerScript("review_form.score_tooltips(\$(\"table.reviewers_scores\"))", "score_tooltips"); } return $t . "</table>\n" . $notetxt; } else { return $notetxt; } }
function run(Contact $user, $qreq, $ssel) { global $Conf; $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection(), "allReviewScores" => 1, "reviewerName" => 1))); // compose scores; NB chair is always forceShow $errors = array(); $texts = $any_scores = array(); $any_decision = $any_reviewer_identity = false; $rf = ReviewForm::get(); $bad_pid = -1; while ($row = PaperInfo::fetch($result, $user)) { if (!$row->reviewSubmitted || $row->paperId == $bad_pid) { /* skip */ } else { if ($whyNot = $user->perm_view_review($row, null, true)) { $errors[] = whyNotText($whyNot, "view reviews for") . "<br />"; $bad_pid = $row->paperId; } else { $a = array("paper" => $row->paperId, "title" => $row->title); if ($row->outcome && $user->can_view_decision($row, true)) { $a["decision"] = $any_decision = $Conf->decision_name($row->outcome); } $view_bound = $user->view_score_bound($row, $row, true); $this_scores = false; foreach ($rf->forder as $field => $f) { if ($f->view_score > $view_bound && $f->has_options && ($row->{$field} || $f->allow_empty)) { $a[$f->abbreviation] = $f->unparse_value($row->{$field}); $any_scores[$f->abbreviation] = $this_scores = true; } } if ($user->can_view_review_identity($row, $row, true)) { $any_reviewer_identity = true; $a["email"] = $row->reviewEmail; $a["reviewername"] = trim($row->reviewFirstName . " " . $row->reviewLastName); } if ($this_scores) { arrayappend($texts[$row->paperId], $a); } } } } if (count($texts)) { $header = array("paper", "title"); if ($any_decision) { $header[] = "decision"; } if ($any_reviewer_identity) { array_push($header, "reviewername", "email"); } $header = array_merge($header, array_keys($any_scores)); downloadCSV($ssel->reorder($texts), $header, "scores", ["selection" => true]); } else { if (!count($errors)) { $errors[] = "No papers selected."; } Conf::msg_error(join("", $errors)); } }
if (isset($_REQUEST[$k]) && !isset($_REQUEST[$v])) { $_REQUEST[$v] = $_GET[$v] = $_POST[$v] = $_REQUEST[$k]; } } foreach (array("p", "r", "c", "accept", "refuse", "decline") as $opt) { if (isset($_REQUEST[$opt])) { $after .= ($after === "" ? "" : "&") . $opt . "=" . urlencode($_REQUEST[$opt]); } } $url = hoturl_site_relative_raw("review", $after); go(hoturl("index", "email=" . urlencode($_REQUEST["email"]) . "&password="******"password"]) . "&go=" . urlencode($url))); } if ($Me->is_empty()) { $Me->escape(); } $rf = ReviewForm::get(); // header function confHeader() { global $paperTable; PaperTable::do_header($paperTable, "review", @$_REQUEST["mode"]); } function errorMsgExit($msg) { global $Conf; confHeader(); $Conf->footerScript("shortcut().add()"); $msg && Conf::msg_error($msg); Conf::$g->footer(); exit; }
function render($sv) { global $Conf, $ConfSitePATH; $rf = ReviewForm::get(); $fmap = array(); foreach ($rf->fmap as $fid => $f) { $fmap[$fid] = $f->has_options; } $samples = json_decode(file_get_contents("{$ConfSitePATH}/src/reviewformlibrary.json")); $req = array(); if ($sv->use_req()) { foreach ($rf->fmap as $fid => $f) { foreach (ReviewForm_SettingParser::$setting_prefixes as $fx) { if (isset($sv->req["{$fx}{$fid}"])) { $req["{$fx}{$fid}"] = $sv->req["{$fx}{$fid}"]; } } } } $Conf->footerHtml('<div id="review_form_caption_description" style="display:none">' . '<p>Enter an HTML description for the review form. Include any guidance you’d like to provide for reviewers. Note that complex HTML will not appear on offline review forms.</p></div>' . '<div id="review_form_caption_options" style="display:none">' . '<p>Enter one option per line, numbered starting from 1 (higher numbers are better). For example:</p> <pre class="entryexample dark">1. Reject 2. Weak reject 3. Weak accept 4. Accept</pre> <p>Or use consecutive capital letters (lower letters are better).</p> <p>Normally scores are mandatory: a review with a missing score cannot be submitted. Add a line “<code>No entry</code>” to make the score optional.</p></div>'); $Conf->footerScript("review_form_settings(" . json_encode($fmap) . "," . json_encode($rf->unparse_full_json()) . "," . json_encode($samples) . "," . json_encode($sv->error_fields()) . "," . json_encode($req) . ")"); echo Ht::hidden("has_review_form", 1), "<div id=\"reviewform_removedcontainer\"></div>", "<div id=\"reviewform_container\"></div>", Ht::button("Add score field", array("onclick" => "review_form_settings.add(1)")), "<span class='sep'></span>", Ht::button("Add text field", array("onclick" => "review_form_settings.add(0)")); }
private function get_reviews() { global $Conf; if ($this->rrow) { $rrows = array($this->rrow); } else { $result = Dbl::qe("select PaperReview.*,\n ContactInfo.firstName, ContactInfo.lastName, ContactInfo.email\n from PaperReview\n join ContactInfo on (ContactInfo.contactId=PaperReview.contactId)\n where PaperReview.paperId=" . $this->row->paperId . " order by reviewOrdinal"); $rrows = edb_orows($result); } // save old au_seerev setting, and reset it so authors can see them. if (!($au_seerev = $Conf->au_seerev)) { $Conf->au_seerev = Conf::AUSEEREV_YES; } $text = ""; $rf = ReviewForm::get(); foreach ($rrows as $row) { if ($row->reviewSubmitted && $this->permissionContact->can_view_review($this->row, $row, false)) { $text .= $rf->pretty_text($this->row, $row, $this->permissionContact, $this->no_send) . "\n"; } } $Conf->au_seerev = $au_seerev; if ($text === "" && $au_seerev == Conf::AUSEEREV_UNLESSINCOMPLETE && count($rrows)) { $text = "[Reviews are hidden since you have incomplete reviews of your own.]\n"; } return $text; }