/** * Called to display the Special:ReviewMerge page * * @param unknown_type $par * @param unknown_type $specialPage */ function wfSpecialReviewMerge($par = NULL, $specialPage) { global $wgOut, $wgScriptPath, $wgUser, $wrSidebarHtml; $reviewForm = new ReviewForm(); // read query parameters into variables $unmerge = ''; if (!$reviewForm->readQueryParms($par)) { $wgOut->setPageTitle('Review merge'); $results = '<p>You must click on a "review" link on Recent Changes or a page history in order to review the merge.</p>'; } else { if ($reviewForm->isMarkPatrolled()) { $wgOut->setPagetitle(wfMsg('markedaspatrolled')); $results = $reviewForm->markPatrolled(); } else { if ($reviewForm->isUnmerge()) { if (!$wgUser->isLoggedIn()) { if (!$wgCommandLineMode && !isset($_COOKIE[session_name()])) { User::SetupSession(); } $title = Title::makeTitle(NS_SPECIAL, 'ReviewMerge/' . $par); $requestData = array(); if ($title) { $requestData['returnto'] = $title->getPrefixedUrl(); } $request = new FauxRequest($requestData); require_once 'includes/SpecialUserlogin.php'; $form = new LoginForm($request); $form->mainLoginForm("You need to sign in to unmerge pages<br/><br/>", ''); return; } if ($wgUser->isBlocked()) { $wgOut->blockedPage(); return; } else { if (wfReadOnly()) { $wgOut->readOnlyPage(); return; } } $wgOut->setPagetitle('Unmerge'); $results = $reviewForm->unmerge(); } else { $wgOut->setPageTitle('Review merge'); $wrSidebarHtml = $reviewForm->getReviewSideText(); $results = $reviewForm->getReviewResults(); $unmerge = $reviewForm->getUnmergeInfo(); } } } $wgOut->addHTML($unmerge . $results); }
/** * Save review form. */ function execute() { $conference =& Request::getConference(); $conferenceId = $conference->getId(); $reviewFormDao =& DAORegistry::getDAO('ReviewFormDAO'); if ($this->reviewFormId != null) { $reviewForm =& $reviewFormDao->getReviewForm($this->reviewFormId, $conferenceId); } if (!isset($reviewForm)) { $reviewForm = new ReviewForm(); $reviewForm->setConferenceId($conferenceId); $reviewForm->setActive(0); $reviewForm->setSequence(REALLY_BIG_NUMBER); } $reviewForm->setTitle($this->getData('title'), null); // Localized $reviewForm->setDescription($this->getData('description'), null); // Localized if ($reviewForm->getId() != null) { $reviewFormDao->updateReviewForm($reviewForm); $reviewFormId = $reviewForm->getId(); } else { $reviewFormId = $reviewFormDao->insertReviewForm($reviewForm); $reviewFormDao->resequenceReviewForms($conferenceId, 0); } }
/** * Internal function to return a ReviewForm object from a row. * @param $row array * @return ReviewForm */ function &_returnReviewFormFromRow(&$row) { $reviewForm = new ReviewForm(); $reviewForm->setId($row['review_form_id']); $reviewForm->setConferenceId($row['conference_id']); $reviewForm->setSequence($row['seq']); $reviewForm->setActive($row['is_active']); $reviewForm->setCompleteCount($row['complete_count']); $reviewForm->setIncompleteCount($row['incomplete_count']); $this->getDataObjectSettings('review_form_settings', 'review_form_id', $row['review_form_id'], $reviewForm); HookRegistry::call('ReviewFormDAO::_returnReviewFormFromRow', array(&$reviewForm, &$row)); return $reviewForm; }
function update_schema_review_word_counts($Conf) { $rf = new ReviewForm($Conf->review_form_json()); do { $q = array(); $result = Dbl::ql("select * from PaperReview where reviewWordCount is null limit 32"); while ($rrow = edb_orow($result)) { $q[] = "update PaperReview set reviewWordCount=" . $rf->word_count($rrow) . " where reviewId=" . $rrow->reviewId; } Dbl::free($result); $Conf->dblink->multi_query(join(";", $q)); while ($Conf->dblink->more_results()) { Dbl::free($Conf->dblink->next_result()); } } while (count($q) == 32); }
function addScores($a) { global $Conf; if ($this->contact->isPC) { foreach (ReviewForm::all_fields() as $f) { if ($f->has_options && strpos(displayOptionsSet("uldisplay"), " {$f->id} ") !== false) { array_push($a, $f->id); } } $this->scoreMax = array(); } return $a; }
function paperQuery($contact, $options = array()) { // Options: // "paperId" => $pid Only paperId $pid (if array, any of those) // "reviewId" => $rid Only paper reviewed by $rid // "commentId" => $c Only paper where comment is $c // "finalized" Only submitted papers // "unsub" Only unsubmitted papers // "accepted" Only accepted papers // "active" Only nonwithdrawn papers // "author" Only papers authored by $contactId // "myReviewRequests" Only reviews requested by $contactId // "myReviews" All reviews authored by $contactId // "myOutstandingReviews" All unsubmitted reviews auth by $contactId // "myReviewsOpt" myReviews, + include papers not yet reviewed // "allReviews" All reviews (multiple rows per paper) // "allReviewScores" All review scores (multiple rows per paper) // "allComments" All comments (multiple rows per paper) // "reviewerName" Include reviewer names // "commenterName" Include commenter names // "reviewer" => $cid Include reviewerConflictType/reviewerReviewType // "tags" Include paperTags // "tagIndex" => $tag Include tagIndex of named tag // "tagIndex" => tag array -- include tagIndex, tagIndex1, ... // "topics" // "options" // "scores" => array(fields to score) // "assignments" // "order" => $sql $sql is SQL 'order by' clause (or empty) global $Opt; $reviewerQuery = isset($options["myReviews"]) || isset($options["allReviews"]) || isset($options["myReviewRequests"]) || isset($options["myReviewsOpt"]) || isset($options["myOutstandingReviews"]); $allReviewerQuery = isset($options["allReviews"]) || isset($options["allReviewScores"]); $scoresQuery = !$reviewerQuery && isset($options["allReviewScores"]); if (is_object($contact)) { $contactId = $contact->contactId; } else { $contactId = (int) $contact; $contact = null; } if (isset($options["reviewer"]) && is_object($options["reviewer"])) { $reviewerContactId = $options["reviewer"]->contactId; } else { if (isset($options["reviewer"])) { $reviewerContactId = $options["reviewer"]; } else { $reviewerContactId = $contactId; } } if (get($options, "author")) { $myPaperReview = null; } else { if ($allReviewerQuery) { $myPaperReview = "MyPaperReview"; } else { $myPaperReview = "PaperReview"; } } // paper selection $paperset = array(); if (isset($options["paperId"])) { $paperset[] = self::_cvt_numeric_set($options["paperId"]); } if (isset($options["reviewId"])) { if (is_numeric($options["reviewId"])) { $result = Dbl::qe("select paperId from PaperReview where reviewId=" . $options["reviewId"]); $paperset[] = self::_cvt_numeric_set(edb_first_columns($result)); } else { if (preg_match('/^(\\d+)([A-Z][A-Z]?)$/i', $options["reviewId"], $m)) { $result = Dbl::qe("select paperId from PaperReview where paperId={$m['1']} and reviewOrdinal=" . parseReviewOrdinal($m[2])); $paperset[] = self::_cvt_numeric_set(edb_first_columns($result)); } else { $paperset[] = array(); } } } if (isset($options["commentId"])) { $result = Dbl::qe("select paperId from PaperComment where commentId" . sql_in_numeric_set(self::_cvt_numeric_set($options["commentId"]))); $paperset[] = self::_cvt_numeric_set(edb_first_columns($result)); } if (count($paperset) > 1) { $paperset = array(call_user_func_array("array_intersect", $paperset)); } $papersel = ""; if (count($paperset)) { $papersel = "paperId" . sql_in_numeric_set($paperset[0]) . " and "; } // prepare query: basic tables $where = array(); $joins = array("Paper"); $cols = array("Paper.*, PaperConflict.conflictType"); $aujoinwhere = null; if (get($options, "author") && $contact && ($aujoinwhere = $contact->actAuthorSql("PaperConflict", true))) { $where[] = $aujoinwhere; } if (get($options, "author") && !$aujoinwhere) { $joins[] = "join PaperConflict on (PaperConflict.paperId=Paper.paperId and PaperConflict.contactId={$contactId} and PaperConflict.conflictType>=" . CONFLICT_AUTHOR . ")"; } else { $joins[] = "left join PaperConflict on (PaperConflict.paperId=Paper.paperId and PaperConflict.contactId={$contactId})"; } // my review $qr = ""; if ($contact && ($tokens = $contact->review_tokens())) { $qr = " or PaperReview.reviewToken in (" . join(", ", $tokens) . ")"; } if (get($options, "myReviewRequests")) { $joins[] = "join PaperReview on (PaperReview.paperId=Paper.paperId and PaperReview.requestedBy={$contactId} and PaperReview.reviewType=" . REVIEW_EXTERNAL . ")"; } else { if (get($options, "myReviews")) { $joins[] = "join PaperReview on (PaperReview.paperId=Paper.paperId and (PaperReview.contactId={$contactId}{$qr}))"; } else { if (get($options, "myOutstandingReviews")) { $joins[] = "join PaperReview on (PaperReview.paperId=Paper.paperId and (PaperReview.contactId={$contactId}{$qr}) and PaperReview.reviewNeedsSubmit!=0)"; } else { if (get($options, "myReviewsOpt")) { $joins[] = "left join PaperReview on (PaperReview.paperId=Paper.paperId and (PaperReview.contactId={$contactId}{$qr}))"; } else { if (get($options, "allReviews") || get($options, "allReviewScores")) { $x = get($options, "reviewLimitSql") ? " and (" . $options["reviewLimitSql"] . ")" : ""; $joins[] = "join PaperReview on (PaperReview.paperId=Paper.paperId{$x})"; } else { if (!get($options, "author")) { $joins[] = "left join PaperReview on (PaperReview.paperId=Paper.paperId and (PaperReview.contactId={$contactId}{$qr}))"; } } } } } } // started reviews if (get($options, "startedReviewCount")) { $joins[] = "left join (select paperId, count(*) count from PaperReview where {$papersel}(reviewSubmitted or reviewNeedsSubmit>0) group by paperId) R_started on (R_started.paperId=Paper.paperId)"; $cols[] = "coalesce(R_started.count,0) startedReviewCount"; } // submitted reviews $j = "select paperId, count(*) count"; $before_ncols = count($cols); if (get($options, "startedReviewCount")) { $cols[] = "coalesce(R_submitted.count,0) reviewCount"; } if (get($options, "scores")) { foreach ($options["scores"] as $fid) { $cols[] = "R_submitted.{$fid}Scores"; if ($myPaperReview) { $cols[] = "{$myPaperReview}.{$fid}"; } $j .= ", group_concat({$fid} order by reviewId) {$fid}Scores"; } } if (get($options, "reviewTypes") || get($options, "reviewIdentities")) { $cols[] = "R_submitted.reviewTypes"; $j .= ", group_concat(reviewType order by reviewId) reviewTypes"; } if (get($options, "reviewIdentities")) { $cols[] = "R_submitted.reviewRequestedBys"; $j .= ", group_concat(requestedBy order by reviewId) reviewRequestedBys"; if ($this->review_blindness() == self::BLIND_OPTIONAL) { $cols[] = "R_submitted.reviewBlinds"; $j .= ", group_concat(reviewBlind order by reviewId) reviewBlinds"; } if ($contact && $contact->review_tokens()) { $cols[] = "R_submitted.reviewTokens"; $j .= ", group_concat(reviewToken order by reviewId) reviewTokens"; } } if (get($options, "reviewRounds")) { $cols[] = "R_submitted.reviewRounds"; $j .= ", group_concat(reviewRound order by reviewId) reviewRounds"; } if (get($options, "reviewWordCounts") && $this->sversion >= 99) { $cols[] = "R_submitted.reviewWordCounts"; $j .= ", group_concat(reviewWordCount order by reviewId) reviewWordCounts"; } if (get($options, "reviewOrdinals")) { $cols[] = "R_submitted.reviewOrdinals"; $j .= ", group_concat(reviewOrdinal order by reviewId) reviewOrdinals"; } if (get($options, "reviewTypes") || get($options, "scores") || get($options, "reviewContactIds") || get($options, "reviewOrdinals") || get($options, "reviewIdentities")) { $cols[] = "R_submitted.reviewContactIds"; $j .= ", group_concat(contactId order by reviewId) reviewContactIds"; } if (count($cols) != $before_ncols) { $joins[] = "left join ({$j} from PaperReview where {$papersel}reviewSubmitted>0 group by paperId) R_submitted on (R_submitted.paperId=Paper.paperId)"; } // assignments if (get($options, "assignments")) { $j = "select paperId, group_concat(contactId order by reviewId) allReviewContactIds, group_concat(reviewType order by reviewId) allReviewTypes, group_concat(reviewRound order by reviewId) allReviewRounds"; $cols[] = "R_all.allReviewContactIds, R_all.allReviewTypes, R_all.allReviewRounds"; $joins[] = "left join ({$j} from PaperReview where {$papersel}true group by paperId) R_all on (R_all.paperId=Paper.paperId)"; } // fields if (get($options, "author")) { $cols[] = "null reviewType, null reviewId, null myReviewType"; } else { // see also papercolumn.php array_push($cols, "PaperReview.reviewType, PaperReview.reviewId", "PaperReview.reviewModified, PaperReview.reviewSubmitted", "PaperReview.reviewNeedsSubmit, PaperReview.reviewOrdinal", "PaperReview.reviewBlind, PaperReview.reviewToken", "PaperReview.contactId as reviewContactId, PaperReview.requestedBy", "max({$myPaperReview}.reviewType) as myReviewType", "max({$myPaperReview}.reviewSubmitted) as myReviewSubmitted", "min({$myPaperReview}.reviewNeedsSubmit) as myReviewNeedsSubmit", "{$myPaperReview}.contactId as myReviewContactId", "PaperReview.reviewRound"); } if ($reviewerQuery || $scoresQuery) { $cols[] = "PaperReview.reviewEditVersion as reviewEditVersion"; $cols[] = ($this->sversion >= 105 ? "PaperReview.reviewFormat" : "null") . " as reviewFormat"; foreach (ReviewForm::all_fields() as $f) { if ($reviewerQuery || $f->has_options) { $cols[] = "PaperReview.{$f->id} as {$f->id}"; } } } if ($myPaperReview == "MyPaperReview") { $joins[] = "left join PaperReview as MyPaperReview on (MyPaperReview.paperId=Paper.paperId and MyPaperReview.contactId={$contactId})"; } if (get($options, "topics")) { $cols[] = "(select group_concat(topicId) from PaperTopic where PaperTopic.paperId=Paper.paperId) topicIds"; } if (get($options, "options") && (isset($this->settingTexts["options"]) || isset($Opt["optionsInclude"])) && PaperOption::count_option_list()) { $cols[] = "(select group_concat(PaperOption.optionId, '#', value) from PaperOption where paperId=Paper.paperId) optionIds"; } else { if (get($options, "options")) { $cols[] = "'' as optionIds"; } } if (get($options, "tags")) { $cols[] = "(select group_concat(' ', tag, '#', tagIndex order by tag separator '') from PaperTag where PaperTag.paperId=Paper.paperId) paperTags"; } if (get($options, "tagIndex") && !is_array($options["tagIndex"])) { $options["tagIndex"] = array($options["tagIndex"]); } if (get($options, "tagIndex")) { foreach ($options["tagIndex"] as $i => $tag) { $cols[] = "(select tagIndex from PaperTag where PaperTag.paperId=Paper.paperId and PaperTag.tag='" . sqlq($tag) . "') tagIndex" . ($i ?: ""); } } if (get($options, "reviewerPreference")) { $joins[] = "left join PaperReviewPreference on (PaperReviewPreference.paperId=Paper.paperId and PaperReviewPreference.contactId={$reviewerContactId})"; $cols[] = "coalesce(PaperReviewPreference.preference, 0) as reviewerPreference"; $cols[] = "PaperReviewPreference.expertise as reviewerExpertise"; } if (get($options, "allReviewerPreference") || get($options, "desirability")) { $subq = "select paperId"; if (get($options, "allReviewerPreference")) { $subq .= ", " . $this->query_all_reviewer_preference() . " as allReviewerPreference"; $cols[] = "APRP.allReviewerPreference"; } if (get($options, "desirability")) { $subq .= ", sum(if(preference<=-100,0,greatest(least(preference,1),-1))) as desirability"; $cols[] = "coalesce(APRP.desirability,0) as desirability"; } $subq .= " from PaperReviewPreference where {$papersel}true group by paperId"; $joins[] = "left join ({$subq}) as APRP on (APRP.paperId=Paper.paperId)"; } if (get($options, "allConflictType")) { $joins[] = "left join (select paperId, group_concat(concat(contactId,' ',conflictType) separator ',') as allConflictType from PaperConflict where {$papersel}conflictType>0 group by paperId) as AllConflict on (AllConflict.paperId=Paper.paperId)"; $cols[] = "AllConflict.allConflictType"; } if (get($options, "reviewer")) { $joins[] = "left join PaperConflict RPC on (RPC.paperId=Paper.paperId and RPC.contactId={$reviewerContactId})"; $joins[] = "left join PaperReview RPR on (RPR.paperId=Paper.paperId and RPR.contactId={$reviewerContactId})"; $cols[] = "RPC.conflictType reviewerConflictType, RPR.reviewType reviewerReviewType"; } if (get($options, "allComments")) { $joins[] = "join PaperComment on (PaperComment.paperId=Paper.paperId)"; $joins[] = "left join PaperConflict as CommentConflict on (CommentConflict.paperId=PaperComment.paperId and CommentConflict.contactId=PaperComment.contactId)"; array_push($cols, "PaperComment.commentId, PaperComment.contactId as commentContactId", "CommentConflict.conflictType as commentConflictType", "PaperComment.timeModified, PaperComment.comment", "PaperComment.replyTo, PaperComment.commentType"); } if (get($options, "reviewerName")) { if ($options["reviewerName"] === "lead" || $options["reviewerName"] === "shepherd") { $joins[] = "left join ContactInfo as ReviewerContactInfo on (ReviewerContactInfo.contactId=Paper." . $options['reviewerName'] . "ContactId)"; } else { if (get($options, "allComments")) { $joins[] = "left join ContactInfo as ReviewerContactInfo on (ReviewerContactInfo.contactId=PaperComment.contactId)"; } else { if (get($options, "reviewerName")) { $joins[] = "left join ContactInfo as ReviewerContactInfo on (ReviewerContactInfo.contactId=PaperReview.contactId)"; } } } array_push($cols, "ReviewerContactInfo.firstName as reviewFirstName", "ReviewerContactInfo.lastName as reviewLastName", "ReviewerContactInfo.email as reviewEmail", "ReviewerContactInfo.lastLogin as reviewLastLogin"); } if (get($options, "foldall")) { $cols[] = "1 as folded"; } // conditions if (count($paperset)) { $where[] = "Paper.paperId" . sql_in_numeric_set($paperset[0]); } if (get($options, "finalized")) { $where[] = "timeSubmitted>0"; } else { if (get($options, "unsub")) { $where[] = "timeSubmitted<=0"; } } if (get($options, "accepted")) { $where[] = "outcome>0"; } if (get($options, "undecided")) { $where[] = "outcome=0"; } if (get($options, "active") || get($options, "myReviews") || get($options, "myReviewRequests")) { $where[] = "timeWithdrawn<=0"; } if (get($options, "myLead")) { $where[] = "leadContactId={$contactId}"; } if (get($options, "unmanaged")) { $where[] = "managerContactId=0"; } $pq = "select " . join(",\n ", $cols) . "\nfrom " . join("\n ", $joins); if (count($where)) { $pq .= "\nwhere " . join("\n and ", $where); } // grouping and ordering if (get($options, "allComments")) { $pq .= "\ngroup by Paper.paperId, PaperComment.commentId"; } else { if ($reviewerQuery || $scoresQuery) { $pq .= "\ngroup by Paper.paperId, PaperReview.reviewId"; } else { $pq .= "\ngroup by Paper.paperId"; } } if (get($options, "order") && $options["order"] != "order by Paper.paperId") { $pq .= "\n" . $options["order"]; } else { $pq .= "\norder by Paper.paperId"; if ($reviewerQuery || $scoresQuery) { $pq .= ", PaperReview.reviewOrdinal"; } if (isset($options["allComments"])) { $pq .= ", PaperComment.commentId"; } } //Conf::msg_debugt($pq); return $pq . "\n"; }
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 do_setting_update($sv) { global $Conf, $Group, $Me, $Now, $Opt, $OptOverride; // parse settings foreach (Si::$all as $si) { account_value($sv, $si); } // check date relationships foreach (array("sub_reg" => "sub_sub", "final_soft" => "final_done") as $dn1 => $dn2) { list($dv1, $dv2) = [$sv->savedv($dn1), $sv->savedv($dn2)]; } if (!$dv1 && $dv2) { $sv->save($dn1, $dv2); } else { if ($dv2 && $dv1 > $dv2) { $sv->set_error($dn1, unparse_setting_error(Si::get($dn1), "Must come before " . Si::get($dn2, "short_description") . ".")); $sv->set_error($dn2); } } if ($sv->has_savedv("sub_sub")) { $sv->save("sub_update", $sv->savedv("sub_sub")); } if (get($Opt, "defaultSiteContact")) { if ($sv->has_savedv("opt.contactName") && get($Opt, "contactName") === $sv->savedv("opt.contactName")) { $sv->save("opt.contactName", null); } if ($sv->has_savedv("opt.contactEmail") && get($Opt, "contactEmail") === $sv->savedv("opt.contactEmail")) { $sv->save("opt.contactEmail", null); } } if ($sv->has_savedv("resp_active") && $sv->savedv("resp_active")) { foreach (explode(" ", $sv->newv("resp_rounds")) as $i => $rname) { $isuf = $i ? "_{$i}" : ""; if ($sv->newv("resp_open{$isuf}") > $sv->newv("resp_done{$isuf}")) { $sv->set_error("resp_open{$isuf}", unparse_setting_error(Si::get("resp_open"), "Must come before " . Si::get("resp_done", "short_description") . ".")); $sv->set_error("resp_done{$isuf}"); } } } // update 'papersub' if ($sv->has_savedv("pc_seeall")) { // see also conference.php if ($sv->savedv("pc_seeall") <= 0) { $x = "timeSubmitted>0"; } else { $x = "timeWithdrawn<=0"; } $num = Dbl::fetch_ivalue("select paperId from Paper where {$x} limit 1") ? 1 : 0; if ($num != $Conf->setting("papersub")) { $sv->save("papersub", $num); } } // Setting relationships if ($sv->has_savedv("sub_open") && $sv->newv("sub_open", 1) <= 0 && $sv->oldv("sub_open") > 0 && $sv->newv("sub_sub") <= 0) { $sv->save("sub_close", $Now); } if ($sv->has_savedv("msg.clickthrough_submit")) { $sv->save("clickthrough_submit", null); } // make settings $changedn = []; if (!$sv->has_errors() && (count($sv->savedv) || count($sv->save_callbacks))) { $tables = "Settings write"; foreach ($sv->need_lock as $t => $need) { if ($need) { $tables .= ", {$t} write"; } } $Conf->qe("lock tables {$tables}"); // load db settings, pre-crosscheck $dbsettings = array(); $result = Dbl::qe("select name, value, data from Settings"); while ($row = edb_row($result)) { $dbsettings[$row[0]] = $row; } Dbl::free($result); // apply settings foreach ($sv->save_callbacks as $si) { $p = $sv->parser($si); $p->save($sv, $si); } $dv = $aq = $av = array(); foreach ($sv->savedv as $n => $v) { if (substr($n, 0, 4) === "opt." && $v !== null) { $okey = substr($n, 4); $oldv = array_key_exists($okey, $OptOverride) ? $OptOverride[$okey] : get($Opt, $okey); $Opt[$okey] = $v[1] === null ? $v[0] : $v[1]; if ($oldv === $Opt[$okey]) { $v = null; } else { if (!array_key_exists($okey, $OptOverride)) { $OptOverride[$okey] = $oldv; } } } if ($v === null ? !isset($dbsettings[$n]) : isset($dbsettings[$n]) && (int) $dbsettings[$n][1] === $v[0] && $dbsettings[$n][2] === $v[1]) { continue; } $changedn[] = $n; if ($v !== null) { $aq[] = "(?, ?, ?)"; array_push($av, $n, $v[0], $v[1]); } else { $dv[] = $n; } } if (count($dv)) { Dbl::qe_apply("delete from Settings where name?a", array($dv)); //Conf::msg_info(Ht::pre_text_wrap(Dbl::format_query_apply("delete from Settings where name?a", array($dv)))); } if (count($aq)) { Dbl::qe_apply("insert into Settings (name, value, data) values\n\t" . join(",\n\t", $aq) . "\n\ton duplicate key update value=values(value), data=values(data)", $av); //Conf::msg_info(Ht::pre_text_wrap(Dbl::format_query_apply("insert into Settings (name, value, data) values\n\t" . join(",\n\t", $aq) . "\n\ton duplicate key update value=values(value), data=values(data)", $av))); } $Conf->qe("unlock tables"); if (count($changedn)) { $Me->log_activity("Updated settings " . join(", ", $changedn)); } $Conf->load_settings(); // contactdb may need to hear about changes to shortName if ($sv->has_savedv("opt.shortName") && get($Opt, "contactdb_dsn") && ($cdb = Contact::contactdb())) { Dbl::ql($cdb, "update Conferences set shortName=? where dbName=?", $Opt["shortName"], $Opt["dbName"]); } } // update the review form in case it's changed ReviewForm::clear_cache(); if (!$sv->has_errors()) { $Conf->save_session("settings_highlight", $sv->error_fields()); if (count($changedn)) { $Conf->confirmMsg("Changes saved."); } else { $Conf->warnMsg("No changes."); } $sv->report(); redirectSelf(); } else { SettingGroup::crosscheck($sv, $Group); $sv->report(); } }
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)")); }
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 preferences_paperpc($scoreinfo) { global $Conf; $time = microtime(true); $this->prefs = array(); foreach ($this->pcm as $cid => $p) { $this->prefs[$cid] = array(); } $all_fields = ReviewForm::all_fields(); $scoredir = 1; if ($scoreinfo === "x") { $score = "1"; } else { if ((substr($scoreinfo, 0, 1) === "-" || substr($scoreinfo, 0, 1) === "+") && isset($all_fields[substr($scoreinfo, 1)])) { $score = "PaperReview." . substr($scoreinfo, 1); $scoredir = substr($scoreinfo, 0, 1) === "-" ? -1 : 1; } else { $score = "PaperReview.overAllMerit"; } } $query = "select Paper.paperId, ? contactId,\n coalesce(PaperConflict.conflictType, 0) as conflictType,\n coalesce(PaperReview.reviewType, 0) as myReviewType,\n coalesce(PaperReview.reviewSubmitted, 0) as myReviewSubmitted,\n coalesce({$score}, 0) as reviewScore,\n Paper.outcome,\n Paper.managerContactId\n from Paper\n left join PaperConflict on (PaperConflict.paperId=Paper.paperId and PaperConflict.contactId=?)\n left join PaperReview on (PaperReview.paperId=Paper.paperId and PaperReview.contactId=?)\n where Paper.paperId ?a\n group by Paper.paperId"; $nmade = 0; foreach ($this->pcm as $cid => $p) { $result = Dbl::qe($query, $cid, $cid, $cid, $this->papersel); // First, collect score extremes $scoreextreme = array(); $rows = array(); while ($row = edb_orow($result)) { if ($row->conflictType > 0 || $row->myReviewType == 0 || $row->myReviewSubmitted == 0 || $row->reviewScore == 0) { $this->prefs[$row->contactId][$row->paperId] = self::PNOASSIGN; } else { if (!isset($scoreextreme[$row->paperId]) || $scoredir * $row->reviewScore > $scoredir * $scoreextreme[$row->paperId]) { $scoreextreme[$row->paperId] = $row->reviewScore; } $rows[] = $row; } } // Then, collect preferences; ignore score differences farther // than 1 score away from the relevant extreme foreach ($rows as $row) { $scoredifference = $scoredir * ($row->reviewScore - $scoreextreme[$row->paperId]); if ($scoredifference >= -1) { $this->prefs[$row->contactId][$row->paperId] = $scoredifference; } } unset($rows); // don't need the memory any more Dbl::free($result); ++$nmade; if ($nmade % 4 == 0) { $this->set_progress(sprintf("Loading reviewer preferences (%d%% done)", (int) ($nmade * 100 / count($this->pcm) + 0.5))); } } $this->make_pref_groups(); $this->profile["preferences"] = microtime(true) - $time; }
function downloadForm($editable) { global $rf, $Conf, $Me, $prow, $paperTable, $Opt; $explicit = true; if ($paperTable->rrow) { $rrows = array($paperTable->rrow); } else { if ($editable) { $rrows = array(); } else { $rrows = $paperTable->viewable_rrows; $explicit = false; } } $text = ""; foreach ($rrows as $rr) { if ($rr->reviewSubmitted) { $text .= downloadView($prow, $rr, $editable); } } foreach ($rrows as $rr) { if (!$rr->reviewSubmitted && ($explicit || $rr->reviewModified)) { $text .= downloadView($prow, $rr, $editable); } } if (count($rrows) == 0 && $editable) { $text .= downloadView($prow, null, $editable); } if (!$explicit) { $paperTable->resolveComments(); foreach ($paperTable->crows as $cr) { if ($Me->can_view_comment($prow, $cr, false)) { $text .= $cr->unparse_text($Me, true) . "\n"; } } } if (!$text) { $whyNot = $Me->perm_view_review($prow, null, null); return Conf::msg_error(whyNotText($whyNot ?: array("fail" => 1), "review")); } if ($editable) { $text = ReviewForm::textFormHeader(count($rrows) > 1) . $text; } $filename = (count($rrows) > 1 ? "reviews" : "review") . "-" . $prow->paperId; if (count($rrows) == 1 && $rrows[0]->reviewSubmitted) { $filename .= unparseReviewOrdinal($rrows[0]->reviewOrdinal); } downloadText($text, $filename, !$editable); }
/** * Save review form. * @see Form::execute() */ function execute() { $press =& Request::getPress(); $pressId = $press->getId(); $reviewFormDao =& DAORegistry::getDAO('ReviewFormDAO'); if ($this->reviewFormId != null) { $reviewForm =& $reviewFormDao->getReviewForm($this->reviewFormId, ASSOC_TYPE_PRESS, $pressId); } if (!isset($reviewForm)) { $reviewForm = new ReviewForm(); $reviewForm->setPressId($pressId); $reviewForm->setActive(0); $reviewForm->setSequence(REALLY_BIG_NUMBER); } $reviewForm->setTitle($this->getData('title'), null); // Localized $reviewForm->setDescription($this->getData('description'), null); // Localized if ($reviewForm->getId() != null) { $reviewFormDao->updateObject($reviewForm); $this->reviewFormId = $reviewForm->getId(); } else { $this->reviewFormId = $reviewFormDao->insertObject($reviewForm); $reviewFormDao->resequenceReviewForms(ASSOC_TYPE_PRESS, $pressId); } $this->reviewForm = $reviewForm; }
function searchQuickref() { global $rowidx, $Conf, $Opt, $Me; // how to report author searches? if ($Conf->subBlindNever()) { $aunote = ""; } else { if (!$Conf->subBlindAlways()) { $aunote = "<br /><span class='hint'>Search uses fields visible to the searcher. For example, PC member searches do not examine anonymous authors.</span>"; } else { $aunote = "<br /><span class='hint'>Search uses fields visible to the searcher. For example, PC member searches do not examine authors.</span>"; } } // does a reviewer tag exist? $retag = meaningful_pc_tag() ?: ""; _searchQuickrefRow("Basics", "", "all papers in the search category"); _searchQuickrefRow("", "story", "“story” in title, abstract, authors{$aunote}"); _searchQuickrefRow("", "119", "paper #119"); _searchQuickrefRow("", "1 2 5 12-24 kernel", "papers in the numbered set with “kernel” in title, abstract, authors"); _searchQuickrefRow("", "\"802\"", "“802” in title, abstract, authors (not paper #802)"); _searchQuickrefRow("", "very new", "“very” <em>and</em> “new” in title, abstract, authors"); _searchQuickrefRow("", "very AND new", "the same"); _searchQuickrefRow("", "\"very new\"", "the phrase “very new” in title, abstract, authors"); _searchQuickrefRow("", "very OR new", "<em>either</em> “very” <em>or</em> “new” in title, abstract, authors"); _searchQuickrefRow("", "(very AND new) OR newest", "use parentheses to group"); _searchQuickrefRow("", "very -new", "“very” <em>but not</em> “new” in title, abstract, authors"); _searchQuickrefRow("", "very NOT new", "the same"); _searchQuickrefRow("", "ve*", "words that <em>start with</em> “ve” in title, abstract, authors"); _searchQuickrefRow("", "*me*", "words that <em>contain</em> “me” in title, abstract, authors"); _searchQuickrefRow("Title", "ti:flexible", "title contains “flexible”"); _searchQuickrefRow("Abstract", "ab:\"very novel\"", "abstract contains “very novel”"); _searchQuickrefRow("Authors", "au:poletto", "author list contains “poletto”"); if ($Me->isPC) { _searchQuickrefRow("", "au:pc", "one or more authors are PC members (author email matches PC email)"); } _searchQuickrefRow("Collaborators", "co:liskov", "collaborators contains “liskov”"); _searchQuickrefRow("Topics", "topic:link", "selected topics match “link”"); $oex = array(); foreach (PaperOption::option_list() as $o) { $oex = array_merge($oex, $o->example_searches()); } if (count($oex)) { $section = "Options"; foreach ($oex as $extype => $oex) { if ($extype === "has") { $desc = "paper has “" . htmlspecialchars($oex[1]->name) . "” submission option"; $oabbr = array(); foreach (PaperOption::option_list() as $ox) { if ($ox !== $oex[1]) { $oabbr[] = "“has:" . htmlspecialchars($ox->abbr) . "”"; } } if (count($oabbr)) { $desc .= '<div class="hint">Other option ' . pluralx(count($oabbr), "search") . ': ' . commajoin($oabbr) . '</div>'; } } else { if ($extype === "yes") { $desc = "same meaning; abbreviations also accepted"; } else { if ($extype === "numeric") { $desc = "paper’s “" . htmlspecialchars($oex[1]->name) . "” option has value > 100"; } else { if ($extype === "selector") { $desc = "paper’s “" . htmlspecialchars($oex[1]->name) . "” option has value “" . htmlspecialchars($oex[1]->selector[1]) . "”"; } else { if ($extype === "attachment-count") { $desc = "paper has more than 2 “" . htmlspecialchars($oex[1]->name) . "” attachments"; } else { if ($extype === "attachment-filename") { $desc = "paper has an “" . htmlspecialchars($oex[1]->name) . "” attachment with a .gif extension"; } else { continue; } } } } } } _searchQuickrefRow($section, $oex[0], $desc); $section = ""; } } _searchQuickrefRow("<a href='" . hoturl("help", "t=tags") . "'>Tags</a>", "#discuss", "tagged “discuss” (“tag:discuss” also works)"); _searchQuickrefRow("", "-#discuss", "not tagged “discuss”"); _searchQuickrefRow("", "order:discuss", "tagged “discuss”, sort by tag order (“rorder:” for reverse order)"); _searchQuickrefRow("", "#disc*", "matches any tag that <em>starts with</em> “disc”"); $cx = null; $cm = array(); foreach (TagInfo::defined_tags() as $t) { foreach ($t->colors ?: array() as $c) { $cx = $cx ?: $c; if ($cx === $c) { $cm[] = "“{$t->tag}”"; } } } if (count($cm)) { array_unshift($cm, "“{$cx}”"); _searchQuickrefRow("", "style:{$cx}", "tagged to appear {$cx} (tagged " . commajoin($cm, "or") . ")"); } _searchQuickrefRow("Reviews", "re:me", "you are a reviewer"); _searchQuickrefRow("", "re:fdabek", "“fdabek” in reviewer name/email"); if ($retag) { _searchQuickrefRow("", "re:#{$retag}", "has a reviewer tagged “#" . $retag . "”"); } _searchQuickrefRow("", "re:4", "four reviewers (assigned and/or completed)"); if ($retag) { _searchQuickrefRow("", "re:#{$retag}>1", "at least two reviewers (assigned and/or completed) tagged “#" . $retag . "”"); } _searchQuickrefRow("", "re:complete<3", "less than three completed reviews<br /><span class=\"hint\">Use “cre:<3” for short.</span>"); _searchQuickrefRow("", "re:incomplete>0", "at least one incomplete review"); _searchQuickrefRow("", "re:inprogress", "at least one in-progress review (started, but not completed)"); _searchQuickrefRow("", "re:primary>=2", "at least two primary reviewers"); _searchQuickrefRow("", "re:secondary", "at least one secondary reviewer"); _searchQuickrefRow("", "re:external", "at least one external reviewer"); _searchQuickrefRow("", "re:primary:fdabek:complete", "“fdabek” has completed a primary review"); if ($r = meaningful_round_name()) { _searchQuickrefRow("", "re:{$r}", "review in round “" . htmlspecialchars($r) . "”"); } _searchQuickrefRow("", "re:auwords<100", "has a review with less than 100 words in author-visible fields"); if ($Conf->setting("rev_ratings") != REV_RATINGS_NONE) { _searchQuickrefRow("", "rate:+", "review was rated positively (“rate:-” and “rate:+>2” also work; can combine with “re:”)"); } _searchQuickrefRow("Comments", "has:cmt", "at least one visible reviewer comment (not including authors’ response)"); _searchQuickrefRow("", "cmt:>=3", "at least <em>three</em> visible reviewer comments"); _searchQuickrefRow("", "has:aucmt", "at least one reviewer comment visible to authors"); _searchQuickrefRow("", "cmt:sylvia", "“sylvia” (in name/email) wrote at least one visible comment; can combine with counts, use reviewer tags"); $rnames = $Conf->resp_round_list(); if (count($rnames) > 1) { _searchQuickrefRow("", "has:response", "has an author’s response"); _searchQuickrefRow("", "has:{$rnames[1]}response", "has {$rnames['1']} response"); } else { _searchQuickrefRow("", "has:response", "has author’s response"); } _searchQuickrefRow("", "anycmt:>1", "at least two visible comments, possibly <em>including</em> author’s response"); _searchQuickrefRow("Leads", "lead:fdabek", "“fdabek” (in name/email) is discussion lead"); _searchQuickrefRow("", "lead:none", "no assigned discussion lead"); _searchQuickrefRow("", "lead:any", "some assigned discussion lead"); _searchQuickrefRow("Shepherds", "shep:fdabek", "“fdabek” (in name/email) is shepherd (“none” and “any” also work)"); _searchQuickrefRow("Conflicts", "conflict:me", "you have a conflict with the paper"); _searchQuickrefRow("", "conflict:fdabek", "“fdabek” (in name/email) has a conflict with the paper<br /><span class='hint'>This search is only available to chairs and to PC members who can see the paper’s author list.</span>"); _searchQuickrefRow("", "conflict:pc", "some PC member has a conflict with the paper"); _searchQuickrefRow("", "conflict:pc>2", "at least three PC members have conflicts with the paper"); _searchQuickrefRow("", "reconflict:\"1 2 3\"", "a reviewer of paper 1, 2, or 3 has a conflict with the paper"); _searchQuickrefRow("Preferences", "pref:fdabek>0", "“fdabek” (in name/email) has review preference > 0<br /><span class='hint'>PC members can search their own preferences; chairs can search anyone’s preferences.</span>"); _searchQuickrefRow("", "pref:X", "some PC member has a preference expertise of “X” (expert)"); _searchQuickrefRow("Status", "status:sub", "paper is submitted for review", "t=all"); _searchQuickrefRow("", "status:unsub", "paper is neither submitted nor withdrawn", "t=all"); _searchQuickrefRow("", "status:withdrawn", "paper has been withdrawn", "t=all"); _searchQuickrefRow("", "has:final", "final copy uploaded"); foreach ($Conf->decision_map() as $dnum => $dname) { if ($dnum) { break; } } $qdname = strtolower($dname); if (strpos($qdname, " ") !== false) { $qdname = "\"{$qdname}\""; } _searchQuickrefRow("Decision", "dec:{$qdname}", "decision is “" . htmlspecialchars($dname) . "” (partial matches OK)"); _searchQuickrefRow("", "dec:yes", "one of the accept decisions"); _searchQuickrefRow("", "dec:no", "one of the reject decisions"); _searchQuickrefRow("", "dec:any", "decision specified"); _searchQuickrefRow("", "dec:none", "decision unspecified"); // find names of review fields to demonstrate syntax $farr = array(array(), array()); foreach (ReviewForm::all_fields() as $f) { $fx = $f->has_options ? 0 : 1; $farr[$fx][] = $f->analyze(); } $t = "Review fields"; if (count($farr[0])) { $r = $farr[0][0]; _searchQuickrefRow($t, $r->abbreviation1() . ":{$r->typical_score}", "at least one completed review has {$r->name_html} score {$r->typical_score}"); _searchQuickrefRow("", "{$r->abbreviation}:{$r->typical_score}", "other abbreviations accepted"); if (count($farr[0]) > 1) { $r2 = $farr[0][1]; _searchQuickrefRow("", strtolower($r2->abbreviation) . ":{$r2->typical_score}", "other fields accepted (here, {$r2->name_html})"); } if (isset($r->typical_score_range)) { _searchQuickrefRow("", "{$r->abbreviation}:{$r->typical_score0}..{$r->typical_score}", "completed reviews’ {$r->name_html} scores are in the {$r->typical_score0}–{$r->typical_score} range<br /><small>(all scores between {$r->typical_score0} and {$r->typical_score})</small>"); _searchQuickrefRow("", "{$r->abbreviation}:{$r->typical_score_range}", "completed reviews’ {$r->name_html} scores <em>fill</em> the {$r->typical_score0}–{$r->typical_score} range<br /><small>(all scores between {$r->typical_score0} and {$r->typical_score}, with at least one {$r->typical_score0} and at least one {$r->typical_score})</small>"); } if (!$r->option_letter) { list($greater, $less, $hint) = array("greater", "less", ""); } else { $hint = "<br /><small>(better scores are closer to A than Z)</small>"; if (defval($Opt, "smartScoreCompare")) { list($greater, $less) = array("better", "worse"); } else { list($greater, $less) = array("worse", "better"); } } _searchQuickrefRow("", "{$r->abbreviation}:>{$r->typical_score}", "at least one completed review has {$r->name_html} score {$greater} than {$r->typical_score}" . $hint); _searchQuickrefRow("", "{$r->abbreviation}:2<={$r->typical_score}", "at least two completed reviews have {$r->name_html} score {$less} than or equal to {$r->typical_score}"); _searchQuickrefRow("", "{$r->abbreviation}:pc>{$r->typical_score}", "at least one completed PC review has {$r->name_html} score {$greater} than {$r->typical_score}"); _searchQuickrefRow("", "{$r->abbreviation}:pc:2>{$r->typical_score}", "at least two completed PC reviews have {$r->name_html} score {$greater} than {$r->typical_score}"); _searchQuickrefRow("", "{$r->abbreviation}:sylvia={$r->typical_score}", "“sylvia” (reviewer name/email) gave {$r->name_html} score {$r->typical_score}"); $t = ""; } if (count($farr[1])) { $r = $farr[1][0]; _searchQuickrefRow($t, $r->abbreviation1() . ":finger", "at least one completed review has “finger” in the {$r->name_html} field"); _searchQuickrefRow($t, "{$r->abbreviation}:finger", "other abbreviations accepted"); _searchQuickrefRow($t, "{$r->abbreviation}:any", "at least one completed review has text in the {$r->name_html} field"); } if (count($farr[0])) { $r = $farr[0][0]; _searchQuickrefRow("<a href=\"" . hoturl("help", "t=formulas") . "\">Formulas</a>", "formula:all({$r->abbreviation}={$r->typical_score})", "all reviews have {$r->name_html} score {$r->typical_score}<br />" . "<span class='hint'><a href=\"" . hoturl("help", "t=formulas") . "\">Formulas</a> can express complex numerical queries across review scores and preferences.</span>"); _searchQuickrefRow("", "f:all({$r->abbreviation}={$r->typical_score})", "“f” is shorthand for “formula”"); _searchQuickrefRow("", "formula:var({$r->abbreviation})>0.5", "variance in {$r->abbreviation} is above 0.5"); _searchQuickrefRow("", "formula:any({$r->abbreviation}={$r->typical_score} && pref<0)", "at least one reviewer had {$r->name_html} score {$r->typical_score} and review preference < 0"); } _searchQuickrefRow("Display", "show:tags show:conflicts", "show tags and PC conflicts in the results"); _searchQuickrefRow("", "hide:title", "hide title in the results"); if (count($farr[0])) { $r = $farr[0][0]; _searchQuickrefRow("", "show:max({$r->abbreviation})", "show a <a href=\"" . hoturl("help", "t=formulas") . "\">formula</a>"); _searchQuickrefRow("", "show:statistics", "show summary statistics for formulas"); _searchQuickrefRow("", "sort:{$r->abbreviation}", "sort by score"); _searchQuickrefRow("", "sort:\"{$r->abbreviation} variance\"", "sort by score variance"); } _searchQuickrefRow("", "sort:-status", "sort by reverse status"); _searchQuickrefRow("", "edit:#discuss", "edit the values for tag “#discuss”"); _searchQuickrefRow("", "search1 THEN search2", "like “search1 OR search2”, but papers matching “search1” are grouped together and appear earlier in the sorting order"); _searchQuickrefRow("", "1-5 THEN 6-10 show:compact", "display searches in compact columns"); _searchQuickrefRow("", "search1 HIGHLIGHT search2", "search for “search1”, but <span class=\"taghl highlightmark\">highlight</span> papers in that list that match “search2” (also try HIGHLIGHT:pink, HIGHLIGHT:green, HIGHLIGHT:blue)"); }
// offline.php -- HotCRP offline review management 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"; if ($Me->is_empty()) { $Me->escape(); } $rf = ReviewForm::get(); // general error messages if (defval($_REQUEST, "post") && !count($_POST)) { $Conf->post_missing_msg(); } // download blank review form action if (isset($_REQUEST["downloadForm"])) { $text = ReviewForm::textFormHeader("blank") . $rf->textForm(null, null, $Me, null) . "\n"; downloadText($text, "review"); } // upload review form action if (isset($_REQUEST["uploadForm"]) && fileUploaded($_FILES["uploadedFile"]) && check_post()) { $tf = $rf->beginTextForm($_FILES["uploadedFile"]["tmp_name"], $_FILES["uploadedFile"]["name"]); while ($req = $rf->parseTextForm($tf)) { $rf->check_save_review($req, $tf, $Me); } $rf->textFormMessages($tf); // Uploading forms may have completed the reviewer's task; recheck roles. Contact::update_rights(); } else { if (isset($_REQUEST["uploadForm"])) { Conf::msg_error("Choose a file first."); }
$Conf->save_session($m[1], $val !== null ? intval($val) : null); } json_exit(["ok" => true]); } else { json_exit(["ok" => false]); } } if ($qreq->fn === "events" && $Me->is_reviewer()) { $from = $qreq->from; if (!$from || !ctype_digit($from)) { $from = $Now; } $entries = $Conf->reviewerActivity($Me, $from, 10); $when = $from; $rows = array(); $rf = ReviewForm::get(); foreach ($entries as $which => $xr) { if ($xr->isComment) { $rows[] = CommentInfo::unparse_flow_entry($xr, $Me, ""); $when = $xr->timeModified; } else { $rows[] = $rf->reviewFlowEntry($Me, $xr, ""); $when = $xr->reviewSubmitted; } } json_exit(["ok" => true, "from" => (int) $from, "to" => (int) $when - 1, "rows" => $rows]); } else { if ($qreq->fn === "events") { json_exit(["ok" => false]); } }
if (isset($_REQUEST[$x])) { echo Ht::hidden($x, $_REQUEST[$x]); } } echo "<table><tr><td><strong>Show:</strong> </td>\n <td class='pad'>"; $Conf->footerScript('foldmap.ul={"aff":2,"tags":3,"topics":1};'); foreach (array("aff" => "Affiliations", "collab" => "Collaborators", "tags" => "Tags", "topics" => "Topics") as $fold => $text) { if (@$pl->have_folds[$fold] !== null) { echo Ht::checkbox("show{$fold}", 1, $pl->have_folds[$fold], array("onchange" => "fold('ul',!this.checked,'{$fold}')")), " ", Ht::label($text), "<br />\n"; } } echo "</td>"; if (isset($pl->scoreMax)) { echo "<td class='pad'>"; $revViewScore = $Me->aggregated_view_score_bound(); foreach (ReviewForm::all_fields() as $f) { if ($f->view_score > $revViewScore && $f->has_options) { $checked = strpos(displayOptionsSet("uldisplay"), $f->id) !== false; echo Ht::checkbox("show{$f->id}", 1, $checked), " ", Ht::label($f->name_html), "<br />"; } } echo "</td>"; } echo "<td>", Ht::submit("redisplay", "Redisplay"), "</td></tr>\n"; if (isset($pl->scoreMax)) { $ss = array(); foreach (array("A", "V", "D") as $k) { /* ghetto array_intersect_key */ if (isset(ListSorter::$score_sorts[$k])) { $ss[$k] = ListSorter::$score_sorts[$k]; }
public function viewable_scores($field, $contact, $forceShow) { $field = is_object($field) ? $field : ReviewForm::field($field); $view = $contact->can_view_review($this, $field->view_score, $forceShow); if ($view || $this->review_type($contact)) { $s = $this->scores($field->id); if ($view) { return $s; } else { if (($my_score = get($s, $contact->contactId)) !== null) { return array($contact->contactId => $my_score); } } } return null; }
// Formula experiment function formulas_qrow($i, $q, $s, $errf) { if ($q === "all") { $q = ""; } $klass = ($errf ? "setting_error " : "") . "hotcrp_searchbox"; $t = '<tr><td class="lentry">' . Ht::entry("q{$i}", $q, array("size" => 40, "placeholder" => "(All)", "class" => $klass)); $t .= " <span style=\"padding-left:1em\">Style:</span> " . Ht::select("s{$i}", array("plain" => "plain", "by-tag" => "by tag", "redtag" => "red", "orangetag" => "orange", "yellowtag" => "yellow", "greentag" => "green", "bluetag" => "blue", "purpletag" => "purple", "graytag" => "gray"), $s !== "" ? $s : "by-tag"); $t .= '</td><td class="nw"><a href="#" class="qx row_up" onclick="return author_change(this,-1)" tabindex="-1">▲</a><a href="#" class="qx row_down" onclick="return author_change(this,1)" tabindex="-1">▼</a><a href="#" class="qx row_kill" onclick="return author_change(this,Infinity)" tabindex="-1">x</a></td></tr>'; return $t; } if ($Graph == "formula") { // derive a sample graph if (!isset($_REQUEST["fx"]) || !isset($_REQUEST["fy"])) { $all_review_fields = ReviewForm::all_fields(); $field1 = @$all_review_fields["overAllMerit"]; $field2 = null; foreach ($all_review_fields as $f) { if ($f->has_options && !$field1) { $field1 = $f; } else { if ($f->has_options && !$field2 && $field1 != $f) { $field2 = $f; } } } unset($_REQUEST["fx"], $_REQUEST["fy"]); if ($field1) { $_REQUEST["fy"] = "avg(" . $field1->analyze()->abbreviation . ")"; }
private function _parse_expr(&$t, $level, $in_qc) { global $Conf; if (($t = ltrim($t)) === "") { return null; } $lpos = -strlen($t); $e = null; if ($t[0] === "(") { $t = substr($t, 1); $e = $this->_parse_ternary($t, false); $t = ltrim($t); if (!$e || $t === "" || $t[0] !== ")") { return null; } $t = substr($t, 1); } else { if ($t[0] === "-" || $t[0] === "+" || $t[0] === "!") { $op = $t[0]; $t = substr($t, 1); if (!($e = $this->_parse_expr($t, self::$opprec["u{$op}"], $in_qc))) { return null; } $e = $op == "!" ? new NegateFexpr($e) : new Fexpr($op, $e); } else { if (preg_match('/\\Aopt(?:ion)?:\\s*(.*)\\z/s', $t, $m)) { $rest = self::_pop_argument($m[1]); $os = PaperSearch::analyze_option_search($rest[1]); foreach ($os->warn as $w) { $this->_error_html[] = $w; } if (!count($os->os) && !count($os->warn)) { $this->_error_html[] = "“" . htmlspecialchars($rest[1]) . "” doesn’t match a submission option."; } if (!count($os->os)) { return null; } foreach ($os->os as $o) { $ex = new OptionFexpr($o->option); if ($o->kind) { $this->_error_html[] = "“" . htmlspecialchars($rest[1]) . "” can’t be used in formulas."; } else { if ($o->value_word === "") { /* stick with raw option fexpr */ } else { if (is_array($o->value) && $o->compar === "!=") { $ex = new NegateFexpr(new InFexpr($ex, $o->value)); } else { if (is_array($o->value)) { $ex = new InFexpr($ex, $o->value); } else { $ex = new Fexpr(get(self::$_oprewrite, $o->compar, $o->compar), $ex, new ConstantFexpr($o->value, $o->option)); } } } } $e = $e ? new Fexpr("||", $e, $ex) : $ex; } if ($os->negate) { $e = new NegateFexpr($e); } $t = $rest[2]; } else { if (preg_match('/\\Anot([\\s(].*|)\\z/i', $t, $m)) { $t = $m[1]; if (!($e = $this->_parse_expr($t, self::$opprec["u!"], $in_qc))) { return null; } $e = new NegateFexpr($e); } else { if (preg_match('/\\A(\\d+\\.?\\d*|\\.\\d+)(.*)\\z/s', $t, $m)) { $e = new ConstantFexpr($m[1] + 0.0); $t = $m[2]; } else { if (preg_match('/\\A(false|true)\\b(.*)\\z/si', $t, $m)) { $e = new ConstantFexpr($m[1], Fexpr::FBOOL); $t = $m[2]; } else { if (preg_match('/\\A(?:pid|paperid)\\b(.*)\\z/si', $t, $m)) { $e = new PidFexpr(); $t = $m[1]; } else { if (preg_match('/\\A(?:dec|decision):\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/si', $t, $m)) { $e = $this->field_search_fexpr(["outcome", PaperSearch::matching_decisions($m[1])]); $t = $m[2]; } else { if (preg_match('/\\A(?:dec|decision)\\b(.*)\\z/si', $t, $m)) { $e = new DecisionFexpr(); $t = $m[1]; } else { if (preg_match('/\\A(?:is|status):\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/si', $t, $m)) { $e = $this->field_search_fexpr(PaperSearch::status_field_matcher($m[1])); $t = $m[2]; } else { if (preg_match('/\\A(?:tag(?:\\s*:\\s*|\\s+)|#)(' . TAG_REGEX . ')(.*)\\z/is', $t, $m) || preg_match('/\\Atag\\s*\\(\\s*(' . TAG_REGEX . ')\\s*\\)(.*)\\z/is', $t, $m)) { $e = new TagFexpr($m[1], false); $t = $m[2]; } else { if (preg_match('/\\Atag(?:v|-?val|-?value)(?:\\s*:\\s*|\\s+)(' . TAG_REGEX . ')(.*)\\z/is', $t, $m) || preg_match('/\\Atag(?:v|-?val|-?value)\\s*\\(\\s*(' . TAG_REGEX . ')\\s*\\)(.*)\\z/is', $t, $m)) { $e = new TagFexpr($m[1], true); $t = $m[2]; } else { if (preg_match('/\\A(r|re|rev|review|r(?:|e|ev|eview)type|(?:|r|re|rev|review)round|reviewer|r(?:|e|ev|eview)(?:|au)words)(?::|(?=#))\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/is', $t, $m)) { $e = $this->_reviewer_decoration($this->_reviewer_base($m[1]), $m[2]); $t = $m[3]; } else { if (preg_match('/\\A((?:r|re|rev|review)(?:type|round|(?:|au)words)|(?:round|reviewer))\\b(.*)\\z/is', $t, $m)) { $e = $this->_reviewer_base($m[1]); $t = $m[2]; } else { if (preg_match('/\\A(my|all|any|avg|average|mean|median|quantile|count|min|max|atminof|atmaxof|argmin|argmax|std(?:d?ev(?:_pop|_samp|[_.][ps])?)?|sum|var(?:iance)?(?:_pop|_samp|[_.][ps])?|wavg)\\b(.*)\\z/is', $t, $m)) { $t = $m[2]; if (!($e = $this->_parse_function($m[1], $t, true))) { return null; } } else { if (preg_match('/\\A(greatest|least|round|floor|trunc|ceil|log|sqrt|pow|exp)\\b(.*)\\z/is', $t, $m)) { $t = $m[2]; if (!($e = $this->_parse_function($m[1], $t, false))) { return null; } } else { if (preg_match('/\\Anull\\b(.*)\\z/s', $t, $m)) { $e = ConstantFexpr::cnull(); $t = $m[1]; } else { if (preg_match('/\\A(?:is:?)?(rev?|pc(?:rev?)?|pri(?:mary)?|sec(?:ondary)?|ext(?:ernal)?)\\b(.*)\\z/is', $t, $m)) { $rt = ReviewSearchMatcher::parse_review_type($m[1]); $op = $rt == 0 || $rt == REVIEW_PC ? ">=" : "=="; $e = new Fexpr($op, new RevtypeFexpr(), new ConstantFexpr($rt, Fexpr::FREVTYPE)); $t = $m[2]; } else { if (preg_match('/\\Atopicscore\\b(.*)\\z/is', $t, $m)) { $e = new TopicScoreFexpr(); $t = $m[1]; } else { if (preg_match('/\\Aconf(?:lict)?\\b(.*)\\z/is', $t, $m)) { $e = new ConflictFexpr(false); $t = $m[1]; } else { if (preg_match('/\\Apcconf(?:lict)?\\b(.*)\\z/is', $t, $m)) { $e = new ConflictFexpr(true); $t = $m[1]; } else { if (preg_match('/\\A(?:rev)?pref\\b(.*)\\z/is', $t, $m)) { $e = new PrefFexpr(false); $t = $m[1]; } else { if (preg_match('/\\A(?:rev)?prefexp(?:ertise)?\\b(.*)\\z/is', $t, $m)) { $e = new PrefFexpr(true); $t = $m[1]; } else { if (preg_match('/\\A([A-Za-z0-9_]+|\\".*?\\")(.*)\\z/s', $t, $m) && $m[1] !== "\"\"" && !preg_match('/\\A\\s*\\(/', $m[2])) { $field = $m[1]; $t = $m[2]; if ($quoted = $field[0] === "\"") { $field = substr($field, 1, strlen($field) - 2); } if (($f = ReviewForm::field_search($field)) && $f->has_options) { $e = new ScoreFexpr($f); } else { if (!$quoted) { $e = new ConstantFexpr($field, false); } else { return null; } } } } } } } } } } } } } } } } } } } } } } } } } } if (!$e) { return null; } $e->set_landmark($lpos, -strlen($t)); while (1) { if (($t = ltrim($t)) === "") { return $e; } else { if (preg_match(self::BINARY_OPERATOR_REGEX, $t, $m)) { $op = $m[0]; $tn = substr($t, strlen($m[0])); } else { if (preg_match('/\\A(and|or)([\\s(].*|)\\z/i', $t, $m)) { $op = strlen($m[1]) == 3 ? "&&" : "||"; $tn = $m[2]; } else { if (!$in_qc && substr($t, 0, 1) === ":") { $op = ":"; $tn = substr($t, 1); } else { return $e; } } } } $opprec = self::$opprec[$op]; if ($opprec < $level) { return $e; } $t = $tn; $op = get(self::$_oprewrite, $op) ?: $op; if (!($e2 = $this->_parse_expr($t, get(self::$_oprassoc, $op) ? $opprec : $opprec + 1, $in_qc))) { return null; } $e = new Fexpr($op, $e, $e2); $e->set_landmark($lpos, -strlen($t)); } }
public function completion_name() { if ($this->score && ($ff = ReviewForm::field($this->score))) { return $ff->abbreviation; } else { return null; } }
private static function check_review_author_seen($prow, $rrow, $contact, $no_update = false) { global $Now; if ($rrow && !get($rrow, "reviewAuthorSeen") && $contact->act_author_view($prow) && !$contact->is_actas_user()) { $rrow->reviewAuthorSeen = $Now; if (!$no_update) { if (!self::$review_author_seen) { register_shutdown_function("ReviewForm::update_review_author_seen"); self::$review_author_seen = array(); } self::$review_author_seen[] = $rrow->reviewId; } } }
function _searchQueryWord($word, $report_error) { global $Conf; // check for paper number or "#TAG" if (preg_match('/\\A#?(\\d+)(?:-#?(\\d+))?\\z/', $word, $m)) { $m[2] = isset($m[2]) && $m[2] ? $m[2] : $m[1]; return new SearchTerm("pn", 0, array(range($m[1], $m[2]), array())); } else { if (substr($word, 0, 1) === "#") { $qe = $this->_searchQueryWord("tag:" . $word, false); if (!$qe->is_false()) { return $qe; } } } // Allow searches like "ovemer>2"; parse as "ovemer:>2". if (preg_match('/\\A([-_A-Za-z0-9]+)((?:[=!<>]=?|≠|≤|≥)[^:]+)\\z/', $word, $m)) { $qe = $this->_searchQueryWord($m[1] . ":" . $m[2], false); if (!$qe->is_false()) { return $qe; } } $keyword = null; if (($colon = strpos($word, ":")) > 0) { $x = substr($word, 0, $colon); if (strpos($x, '"') === false) { $keyword = get(self::$_keywords, $x) ?: $x; $word = substr($word, $colon + 1); if ($word === false) { $word = ""; } } } // Treat unquoted "*", "ANY", and "ALL" as special; return true. if ($word === "*" || $word === "ANY" || $word === "ALL" || $word === "") { return new SearchTerm("t"); } else { if ($word === "NONE") { return new SearchTerm("f"); } } $qword = $word; $quoted = $word[0] === '"'; $negated = false; if ($quoted) { $word = str_replace('*', '\\*', preg_replace('/(?:\\A"|"\\z)/', '', $word)); } if ($keyword === "notag") { $keyword = "tag"; $negated = true; } $qt = array(); if ($keyword ? $keyword === "ti" : isset($this->fields["ti"])) { $this->_searchField($word, "ti", $qt); } if ($keyword ? $keyword === "ab" : isset($this->fields["ab"])) { $this->_searchField($word, "ab", $qt); } if ($keyword ? $keyword === "au" : isset($this->fields["au"])) { $this->_searchAuthors($word, $qt, $keyword, $quoted); } if ($keyword ? $keyword === "co" : isset($this->fields["co"])) { $this->_searchField($word, "co", $qt); } if ($keyword ? $keyword === "re" : isset($this->fields["re"])) { $this->_search_reviewer($qword, "re", $qt); } else { if ($keyword && get(self::$_canonical_review_keywords, $keyword)) { $this->_search_reviewer($qword, $keyword, $qt); } } if (preg_match('/\\A(?:(?:draft-?)?\\w*resp(?:onse)|\\w*resp(?:onse)?(-?draft)?|cmt|aucmt|anycmt)\\z/', $keyword)) { $this->_search_comment($word, $keyword, $qt, $quoted); } if ($keyword === "pref" && $this->amPC) { $this->_search_revpref($word, $qt, $quoted, false); } if ($keyword === "prefexp" && $this->amPC) { $this->_search_revpref($word, $qt, $quoted, true); } foreach (array("lead", "shepherd", "manager") as $ctype) { if ($keyword === $ctype) { $x = $this->_one_pc_matcher($word, $quoted); $qt[] = new SearchTerm("pf", self::F_XVIEW, array("{$ctype}ContactId", $x)); if ($ctype === "manager" && $word === "me" && !$quoted && $this->privChair) { $qt[] = new SearchTerm("pf", self::F_XVIEW, array("{$ctype}ContactId", "=0")); } } } if (($keyword ? $keyword === "tag" : isset($this->fields["tag"])) || $keyword === "order" || $keyword === "rorder") { $this->_search_tags($word, $keyword, $qt); } if ($keyword === "color") { $this->_search_color($word, $qt); } if ($keyword === "topic") { $type = "topic"; $value = null; if ($word === "none" || $word === "any") { $value = $word; } else { $x = strtolower(simplify_whitespace($word)); $tids = array(); foreach ($Conf->topic_map() as $tid => $tname) { if (strstr(strtolower($tname), $x) !== false) { $tids[] = $tid; } } if (count($tids) == 0 && $word !== "none" && $word !== "any") { $this->warn("“" . htmlspecialchars($x) . "” does not match any defined paper topic."); $type = "f"; } else { $value = $tids; } } $qt[] = new SearchTerm($type, self::F_XVIEW, $value); } if ($keyword === "option") { $this->_search_options($word, $qt, true); } if ($keyword === "status" || $keyword === "is") { $this->_search_status($word, $qt, $quoted, true); } if ($keyword === "decision") { $this->_search_status($word, $qt, $quoted, false); } if ($keyword === "conflict" && $this->amPC) { $this->_search_conflict($word, $qt, $quoted, false); } if ($keyword === "pcconflict" && $this->amPC) { $this->_search_conflict($word, $qt, $quoted, true); } if ($keyword === "reconflict" && $this->privChair) { $this->_searchReviewerConflict($word, $qt, $quoted); } if ($keyword === "round" && $this->amPC) { $this->reviewAdjust = true; if ($word === "none") { $qt[] = new SearchTerm("revadj", 0, array("round" => array(0))); } else { if ($word === "any") { $qt[] = new SearchTerm("revadj", 0, array("round" => range(1, count($Conf->round_list()) - 1))); } else { $x = simplify_whitespace($word); $rounds = Text::simple_search($x, $Conf->round_list()); if (count($rounds) == 0) { $this->warn("“" . htmlspecialchars($x) . "” doesn’t match a review round."); $qt[] = new SearchTerm("f"); } else { $qt[] = new SearchTerm("revadj", 0, array("round" => array_keys($rounds))); } } } } if ($keyword === "rate") { $this->_searchReviewRatings($word, $qt); } if ($keyword === "has") { $this->_search_has($word, $qt, $quoted); } if ($keyword === "formula") { $this->_search_formula($word, $qt, $quoted); } if ($keyword === "ss" && $this->amPC) { if ($nextq = self::_expand_saved_search($word, $this->_ssRecursion)) { $this->_ssRecursion[$word] = true; $qe = $this->_searchQueryType($nextq); unset($this->_ssRecursion[$word]); } else { $qe = null; } if (!$qe && $nextq === false) { $this->warn("Saved search “" . htmlspecialchars($word) . "” is incorrectly defined in terms of itself."); } else { if (!$qe && !$Conf->setting_data("ss:{$word}")) { $this->warn("There is no “" . htmlspecialchars($word) . "” saved search."); } else { if (!$qe) { $this->warn("The “" . htmlspecialchars($word) . "” saved search is defined incorrectly."); } } } $qt[] = $qe ?: new SearchTerm("f"); } if ($keyword === "HEADING") { $heading = simplify_whitespace($word); $qt[] = SearchTerm::make_float(["heading" => $heading]); } if ($keyword === "show" || $keyword === "hide" || $keyword === "edit" || $keyword === "sort" || $keyword === "showsort" || $keyword === "editsort") { $editing = strpos($keyword, "edit") !== false; $sorting = strpos($keyword, "sort") !== false; $views = array(); $a = $keyword === "hide" ? false : ($editing ? "edit" : true); $word = simplify_whitespace($word); $ch1 = substr($word, 0, 1); if ($ch1 === "-" && !$sorting) { list($a, $word) = array(false, substr($word, 1)); } $wtype = $word; if ($sorting) { $sort = self::parse_sorter($wtype); $wtype = $sort->type; } if ($wtype !== "" && $keyword !== "sort") { $views[$wtype] = $a; } $f = array("view" => $views); if ($sorting) { $f["sort"] = array($word); } $qt[] = SearchTerm::make_float($f); } // Finally, look for a review field. if ($keyword && !isset(self::$_keywords[$keyword]) && count($qt) == 0) { if ($field = ReviewForm::field_search($keyword)) { $this->_search_review_field($word, $field, $qt, $quoted); } else { if (!$this->_search_options("{$keyword}:{$word}", $qt, false) && $report_error) { $this->warn("Unrecognized keyword “" . htmlspecialchars($keyword) . "”."); } } } $qe = SearchTerm::make_op("or", $qt); return $negated ? SearchTerm::make_not($qe) : $qe; }
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)); } }
function importReviewForms() { assert($this->xml->name == 'reviewForms'); $journal = $this->journal; $reviewFormDao =& DAORegistry::getDAO('ReviewFormDAO'); $reviewFormElementDao =& DAORegistry::getDAO('ReviewFormElementDAO'); $this->nextElement(); while ($this->xml->name == 'reviewForm') { $reviewFormXML = $this->getCurrentElementAsDom(); $reviewForm = new ReviewForm(); $reviewForm->setSequence((int) $reviewFormXML->sequence); $reviewForm->setActive((int) $reviewFormXML->active); $reviewForm->setAssocType(ASSOC_TYPE_JOURNAL); $reviewForm->setAssocId($this->journal->getId()); $reviewFormDao->insertObject($reviewForm); $this->idTranslationTable->register(INTERNAL_TRANSFER_OBJECT_REVIEW_FORM, (int) $reviewFormXML->oldId, $reviewForm->getId()); foreach ($reviewFormXML->reviewElement as $reviewElementXML) { $reviewFormElement = new ReviewFormElement(); $reviewFormElement->setReviewFormId($reviewForm->getId()); $reviewFormElement->setSequence((int) $reviewElementXML->sequence); $reviewFormElement->setElementType((int) $reviewElementXML->elementType); $reviewFormElement->setRequired((int) $reviewElementXML->required); $reviewFormElement->setIncluded((int) $reviewElementXML->included); $reviewFormElementDao->insertObject($reviewFormElement); $this->idTranslationTable->register(INTERNAL_TRANSFER_OBJECT_REVIEW_FORM_ELEMENT, (int) $reviewElementXML->oldId, $reviewFormElement->getId()); $this->restoreDataObjectSettings($reviewFormElementDao, $reviewElementXML->settings, 'review_form_element_settings', 'review_form_element_id', $reviewFormElement->getId()); } $this->restoreDataObjectSettings($reviewFormDao, $reviewFormXML->settings, 'review_form_settings', 'review_form_id', $reviewForm->getId()); $this->nextElement(); } }
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; }