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 .= "&nbsp;#" . $prow->paperId . unparseReviewOrdinal($rr->reviewOrdinal);
        } else {
            if ($rr->reviewType == REVIEW_SECONDARY && $rr->reviewNeedsSubmit <= 0) {
                $id .= "&nbsp;(delegated)";
            } else {
                if ($rr->reviewModified > 0) {
                    $id .= "&nbsp;(in&nbsp;progress)";
                } else {
                    $id .= "&nbsp;(not&nbsp;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 .= '&nbsp;<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;
 }