function _paperLink($row) { global $Conf; $pt = $this->_paper_link_page ? $this->_paper_link_page : "paper"; $pl = "p=" . $row->paperId; $doreview = isset($row->reviewId) && isset($row->reviewFirstName); if ($doreview) { $rord = unparseReviewOrdinal($row); if ($pt == "paper" && $row->reviewSubmitted > 0) { $pl .= "#r" . $rord; } else { $pl .= "&r=" . $rord; if ($row->reviewSubmitted > 0) { $pl .= "&m=r"; } } } else { if ($pt === "review") { $pt = "paper"; } } return hoturl($pt, $pl); }
function reviewLinks($prow, $rrows, $crows, $rrow, $mode, &$allreviewslink) { global $Conf, $Me; $conflictType = $Me->view_conflict_type($prow); $allow_admin = $Me->allow_administer($prow); $any_comments = false; $admin = $Me->can_administer($prow); $xsep = ' <span class="barsep">·</span> '; $nvisible = 0; $myrr = null; if ($rrows) { foreach ($rrows as $rr) { if ($Me->can_view_review($prow, $rr, null)) { $nvisible++; } if ($rr->contactId == $Me->contactId || !$myrr && $Me->is_my_review($rr)) { $myrr = $rr; } } } // comments $pret = ""; if ($crows && count($crows) > 0 && !$rrow && $mode !== "edit") { $cids = array(); $cnames = array(); $tagger = new Tagger($Me); foreach ($crows as $cr) { if ($Me->can_view_comment($prow, $cr, null)) { if ($Me->can_view_comment_identity($prow, $cr, null)) { $n = Text::abbrevname_html($cr->user()); } else { $n = "anonymous"; } if ($cr->commentType & COMMENTTYPE_RESPONSE) { $rname = $Conf->resp_round_name($cr->commentRound); $n = $n === "anonymous" ? "" : " ({$n})"; if ($cr->commentType & COMMENTTYPE_DRAFT && $rname != "1") { $n = "<i>Draft {$rname} Response</i>{$n}"; } else { if ($cr->commentType & COMMENTTYPE_DRAFT) { $n = "<i>Draft Response</i>{$n}"; } else { if ($rname != "1") { $n = "<i>{$rname} Response</i>{$n}"; } else { $n = "<i>Response</i>{$n}"; } } } } $cids[] = $cid = CommentInfo::unparse_html_id($cr); $tclass = "cmtlink"; if ($cr->commentTags && ($tags = Tagger::strip_nonviewable($cr->commentTags, $Me)) && $Me->can_view_comment_tags($prow, $cr, null) && ($color = TagInfo::color_classes($tags))) { if (TagInfo::classes_have_colors($color)) { $tclass .= " tagcolorspan"; } $tclass .= " {$color} taghl"; } $cnames[] = '<a class="' . $tclass . '" href="#' . $cid . '">' . $n . '</a>'; } } if (count($cids) > 0) { $pret = '<div class="revnotes"><a href="#' . $cids[0] . '"><strong>' . plural(count($cids), "Comment") . '</strong></a>: <span class="nb">' . join(',</span> <span class="nb">', $cnames) . "</span></div>"; $any_comments = true; } } $t = ""; // see all reviews $allreviewslink = false; if (($nvisible > 1 || $nvisible > 0 && !$myrr) && ($mode !== "p" || $rrow)) { $allreviewslink = true; $x = '<a href="' . hoturl("paper", "p={$prow->paperId}") . '" class="xx">' . Ht::img("view24.png", "[All reviews]", "dlimg") . " <u>All reviews</u></a>"; $t .= ($t === "" ? "" : $xsep) . $x; } // edit paper if ($mode !== "edit" && $prow->conflictType >= CONFLICT_AUTHOR && !$Me->can_administer($prow)) { $x = '<a href="' . hoturl("paper", "p={$prow->paperId}&m=edit") . '" class="xx">' . Ht::img("edit24.png", "[Edit paper]", "dlimg") . " <u><strong>Edit paper</strong></u></a>"; $t .= ($t === "" ? "" : $xsep) . $x; } // edit review if ($mode === "re" || $mode === "assign" && $t !== "" || !$prow) { /* no link */ } else { if ($myrr && $rrow != $myrr) { $myrlink = unparseReviewOrdinal($myrr); $a = '<a href="' . hoturl("review", "p={$prow->paperId}&r={$myrlink}") . '" class="xx">'; if ($Me->can_review($prow, $myrr)) { $x = $a . Ht::img("review24.png", "[Edit review]", "dlimg") . " <u><b>Edit your review</b></u></a>"; } else { $x = $a . Ht::img("review24.png", "[Your review]", "dlimg") . " <u><b>Your review</b></u></a>"; } $t .= ($t === "" ? "" : $xsep) . $x; } else { if (!$myrr && !$rrow && $Me->can_review($prow, null)) { $x = '<a href="' . hoturl("review", "p={$prow->paperId}&m=re") . '" class="xx">' . Ht::img("review24.png", "[Write review]", "dlimg") . " <u><b>Write review</b></u></a>"; $t .= ($t === "" ? "" : $xsep) . $x; } } } // review assignments if ($mode !== "assign" && $mode !== "edit" && $Me->can_request_review($prow, true)) { $x = '<a href="' . hoturl("assign", "p={$prow->paperId}") . '" class="xx">' . Ht::img("assign24.png", "[Assign]", "dlimg") . " <u>" . ($admin ? "Assign reviews" : "External reviews") . "</u></a>"; $t .= ($t === "" ? "" : $xsep) . $x; } // new comment $nocmt = preg_match('/\\A(?:assign|contact|edit|re)\\z/', $mode); if (!$allreviewslink && !$nocmt && $Me->can_comment($prow, null)) { $x = '<a href="#cnew" onclick="return papercomment.edit_new()" class="xx">' . Ht::img("comment24.png", "[Add comment]", "dlimg") . " <u>Add comment</u></a>"; $t .= ($t === "" ? "" : $xsep) . $x; $any_comments = true; } // new response if (!$nocmt && ($prow->conflictType >= CONFLICT_AUTHOR || $allow_admin) && ($rrounds = $Conf->time_author_respond())) { foreach ($rrounds as $i => $rname) { $cid = ($i ? $rname : "") . "response"; $what = "Add"; if ($crows) { foreach ($crows as $cr) { if ($cr->commentType & COMMENTTYPE_RESPONSE && $cr->commentRound == $i) { $what = "Edit"; if ($cr->commentType & COMMENTTYPE_DRAFT) { $what = "Edit draft"; } } } } $x = '<a href="#' . $cid . '" onclick=\'return papercomment.edit_response(' . json_encode($rname) . ')\' class="xx">' . Ht::img("comment24.png", "[{$what} response]", "dlimg") . " " . ($conflictType >= CONFLICT_AUTHOR ? '<u style="font-weight:bold">' : '<u>') . $what . ($i ? " {$rname}" : "") . ' response</u></a>'; $t .= ($t === "" ? "" : $xsep) . $x; $any_comments = true; } } // override conflict if ($allow_admin && !$admin) { $x = '<a href="' . selfHref(array("forceShow" => 1)) . '" class="xx">' . Ht::img("override24.png", "[Override]", "dlimg") . " <u>Override conflict</u></a> to show reviewers and allow editing"; $t .= ($t === "" ? "" : $xsep) . $x; } else { if ($Me->privChair && !$allow_admin) { $x = "You can’t override your conflict because this paper has an administrator."; $t .= ($t === "" ? "" : $xsep) . $x; } } if ($any_comments) { CommentInfo::echo_script($prow); } if (($list = SessionList::active()) && ($pret || $t)) { return '<div class="has_hotcrp_list" data-hotcrp-list="' . $list->listno . '">' . $pret . $t . '</div>'; } else { return $pret . $t; } }
function unparseReviewOrdinal($ord) { if ($ord === null) { return "x"; } else { if (is_object($ord)) { if ($ord->reviewOrdinal) { return $ord->paperId . unparseReviewOrdinal($ord->reviewOrdinal); } else { return $ord->reviewId; } } else { if ($ord <= 26) { return chr($ord + 64); } else { return chr(intval(($ord - 1) / 26) + 64) . chr(($ord - 1) % 26 + 65); } } } }
function reviewFlowEntry($contact, $rrow, $trclass) { // See also CommentInfo::unparse_flow_entry global $Conf; $barsep = " <span class='barsep'>·</span> "; $a = "<a href='" . hoturl("paper", "p={$rrow->paperId}#r" . unparseReviewOrdinal($rrow)) . "'"; $t = "<tr class='{$trclass}'><td class='pl_activityicon'>" . $a . ">" . Ht::img("review24.png", "[Review]", "dlimg") . "</a></td><td class='pl_activityid pnum'>" . $a . ">#{$rrow->paperId}</a></td><td class='pl_activitymain'><small>" . $a . " class=\"ptitle\">" . htmlspecialchars($rrow->shortTitle); if (strlen($rrow->shortTitle) != strlen($rrow->title)) { $t .= "..."; } $t .= "</a>"; if ($contact->can_view_review_time($rrow, $rrow)) { $time = $Conf->parseableTime($rrow->reviewModified, false); } else { $time = $Conf->unparse_time_obscure($Conf->obscure_time($rrow->reviewModified)); } $t .= $barsep . $time; if ($contact->can_view_review_identity($rrow, $rrow, false)) { $t .= $barsep . "<span class='hint'>review by</span> " . Text::user_html($rrow->reviewFirstName, $rrow->reviewLastName, $rrow->reviewEmail); } $t .= "</small><br /><a class='q'" . substr($a, 3) . ">"; $revViewScore = $contact->view_score_bound($rrow, $rrow); if ($rrow->reviewSubmitted) { $t .= "Review #" . unparseReviewOrdinal($rrow) . " submitted"; $xbarsep = $barsep; } else { $xbarsep = ""; } foreach ($this->forder as $field => $f) { if ($f->view_score > $revViewScore && $f->has_options && $rrow->{$field}) { $t .= $xbarsep . $f->name_html . " " . $f->unparse_value($rrow->{$field}, ReviewField::VALUE_SC); $xbarsep = $barsep; } } return $t . "</a></td></tr>"; }
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); }
xassert_match($x->a[0], ",^x.txt:2(?::|\$),"); xassert_match($x->a[1], ",^x.txt:2(?::|\$),"); xassert_match($x->b->c, ",^x.txt:4(?::|\$),"); xassert_match($x->b->__LANDMARK__, ",^x.txt:3(?::|\$),"); // obscure_time tests $t = $Conf->parse_time("1 Sep 2010 00:00:01"); $t0 = $Conf->obscure_time($t); xassert_eqq($Conf->unparse_time_obscure($t0), "1 Sep 2010"); xassert_eqq($Conf->printableTime($t0), "1 Sep 2010 12pm EDT"); $t = $Conf->parse_time("1 Sep 2010 23:59:59"); $t0 = $Conf->obscure_time($t); xassert_eqq($Conf->unparse_time_obscure($t0), "1 Sep 2010"); xassert_eqq($Conf->printableTime($t0), "1 Sep 2010 12pm EDT"); // review ordinal tests foreach ([1 => "A", 26 => "Z", 27 => "AA", 28 => "AB", 51 => "AY", 52 => "AZ", 53 => "BA", 54 => "BB", 702 => "ZZ"] as $n => $t) { xassert_eqq(unparseReviewOrdinal($n), $t); xassert_eqq(parseReviewOrdinal($t), $n); } // ReviewField::make_abbreviation tests xassert_eqq(ReviewField::make_abbreviation("novelty", 0, 0), "Nov"); xassert_eqq(ReviewField::make_abbreviation("novelty is an amazing", 0, 0), "NovIsAma"); xassert_eqq(ReviewField::make_abbreviation("novelty is an AWESOME", 0, 0), "NovIsAWESOME"); xassert_eqq(ReviewField::make_abbreviation("novelty isn't an AWESOME", 0, 0), "NovIsnAWESOME"); xassert_eqq(ReviewField::make_abbreviation("novelty isn't an AWESOME", 0, 1), "novelty-isnt-awesome"); xassert_eqq(ReviewField::make_abbreviation("_format", 0, 1), "format"); // utf8_word_prefix, etc. tests xassert_eqq(UnicodeHelper::utf8_prefix("aaaaaaaa", 7), "aaaaaaa"); xassert_eqq(UnicodeHelper::utf8_prefix("aaaaaaaa", 8), "aaaaaaaa"); xassert_eqq(UnicodeHelper::utf8_prefix("aaaaaaaa", 9), "aaaaaaaa"); xassert_eqq(UnicodeHelper::utf8_prefix("áááááááá", 7), "ááááááá"); xassert_eqq(UnicodeHelper::utf8_prefix("áááááááá", 8), "áááááááá");
private function _combine_data($result) { global $Me; $data = []; if ($this->fx->result_format() === Fexpr::FREVIEWER) { $this->_prepare_reviewer_color($Me); } $fxf = $this->fx->compile_function($Me); list($fytrack, $fycombine) = $this->fy->compile_combine_functions($Me); $reviewf = null; if ($this->fx->needs_review() || $this->fy->datatypes) { $reviewf = Formula::compile_indexes_function($Me, ($this->fx->needs_review() ? $this->fx->datatypes : 0) | $this->fy->datatypes); } while ($prow = PaperInfo::fetch($result, $Me)) { if (!$Me->can_view_paper($prow)) { continue; } $queries = $this->papermap[$prow->paperId]; $s = $ps = $this->_paper_style($prow); $revs = $reviewf ? $reviewf($prow, $Me) : [null]; foreach ($revs as $rcid) { if (($x = $fxf($prow, $rcid, $Me)) === null) { continue; } if ($ps === self::REVIEWER_COLOR) { $s = get($this->reviewer_color, $d[0]) ?: ""; } $d = [$x, $fytrack($prow, $rcid, $Me), $prow->paperId, $s]; if ($rcid && ($o = $prow->review_ordinal($rcid))) { $d[2] .= unparseReviewOrdinal($o); } foreach ($queries as $q) { $q && ($d[4] = $q); $data[] = $d; } } } $is_sum = $this->fy->is_sum(); usort($data, "FormulaGraph::barchart_compare"); $ndata = []; for ($i = 0; $i != count($data); $i = $j) { $d = [$data[$i][0], [$data[$i][1]], [$data[$i][2]], $data[$i][3], get($data[$i], 4)]; for ($j = $i + 1; $j != count($data) && $data[$j][0] == $d[0] && get($data[$j], 4) == $d[4] && (!$is_sum || $data[$j][3] == $d[3]); ++$j) { $d[1][] = $data[$j][1]; $d[2][] = $data[$j][2]; if ($d[3] && $d[3] != $data[$j][3]) { $d[3] = ""; } } $d[1] = $fycombine($d[1]); if (!$d[4]) { array_pop($d); $d[3] || array_pop($d); } $ndata[] = $d; } return $ndata; }
function content($fieldId, $row) { global $Conf; switch ($fieldId) { case self::FIELD_NAME: $t = Text::name_html($row); if (trim($t) == "") { $t = "[No name]"; } $t = '<span class="taghl">' . $t . '</span>'; if ($this->contact->privChair) { $t = "<a href=\"" . hoturl("profile", "u=" . urlencode($row->email) . $this->contactLinkArgs) . "\"" . ($row->disabled ? " class='uu'" : "") . ">{$t}</a>"; } if ($row->roles & Contact::ROLE_CHAIR) { $t .= ' <span class="pcrole">(chair)</span>'; } else { if (($row->roles & (Contact::ROLE_ADMIN | Contact::ROLE_PC)) == (Contact::ROLE_ADMIN | Contact::ROLE_PC)) { $t .= ' <span class="pcrole">(PC, sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_ADMIN) { $t .= ' <span class="pcrole">(sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_PC && $this->limit != "pc") { $t .= ' <span class="pcrole">(PC)</span>'; } } } } if ($this->contact->privChair && $row->email != $this->contact->email) { $t .= " <a href=\"" . hoturl("index", "actas=" . urlencode($row->email)) . "\">" . Ht::img("viewas.png", "[Act as]", array("title" => "Act as " . Text::name_text($row))) . "</a>"; } if ($row->disabled && $this->contact->isPC) { $t .= ' <span class="hint">(disabled)</span>'; } return $t; case self::FIELD_EMAIL: if (!$this->contact->isPC) { return ""; } $e = htmlspecialchars($row->email); if (strpos($row->email, "@") === false) { return $e; } else { return "<a href=\"mailto:{$e}\">{$e}</a>"; } case self::FIELD_AFFILIATION: case self::FIELD_AFFILIATION_ROW: return htmlspecialchars($row->affiliation); case self::FIELD_LASTVISIT: if (!$row->lastLogin) { return "Never"; } return $Conf->printableTimeShort($row->lastLogin); case self::FIELD_SELECTOR: case self::FIELD_SELECTOR_ON: $this->any->sel = true; $c = ""; if ($fieldId == self::FIELD_SELECTOR_ON) { $c = " checked='checked'"; } return "<input type='checkbox' class='cb' name='pap[]' value='{$row->contactId}' tabindex='1' id='psel{$this->count}' onclick='rangeclick(event,this)' {$c}/>"; case self::FIELD_HIGHTOPICS: case self::FIELD_LOWTOPICS: if (!defval($row, "topicIds")) { return ""; } $wanthigh = $fieldId == self::FIELD_HIGHTOPICS; $topics = array_combine(explode(",", $row->topicIds), explode(",", $row->topicInterest)); $nt = $nti = array(); foreach ($topics as $k => $v) { if ($wanthigh ? $v > 0 : $v < 0) { $nt[] = $k; $nti[] = $v; } } if (count($nt)) { return PaperInfo::unparse_topic_list_html($nt, $nti, true); } else { return ""; } case self::FIELD_REVIEWS: if (!$row->numReviews && !$row->numReviewsSubmitted) { return ""; } $a1 = "<a href=\"" . hoturl("search", "t=s&q=re:" . urlencode($row->email)) . "\">"; if ($row->numReviews == $row->numReviewsSubmitted) { return "{$a1}<b>{$row->numReviewsSubmitted}</b></a>"; } else { return "{$a1}<b>{$row->numReviewsSubmitted}</b>/{$row->numReviews}</a>"; } case self::FIELD_LEADS: if (!$row->numLeads) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=lead:" . urlencode($row->email)) . "\">{$row->numLeads}</a>"; case self::FIELD_SHEPHERDS: if (!$row->numShepherds) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=shepherd:" . urlencode($row->email)) . "\">{$row->numShepherds}</a>"; case self::FIELD_REVIEW_RATINGS: if (!$row->numReviews && !$row->numReviewsSubmitted || !$row->numRatings) { return ""; } $a = array(); $b = array(); if ($row->sumRatings > 0) { $a[] = $row->sumRatings . " positive"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:%2B") . "\">+" . $row->sumRatings . "</a>"; } if ($row->sumRatings < $row->numRatings) { $a[] = $row->numRatings - $row->sumRatings . " negative"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:-") . "\">−" . ($row->numRatings - $row->sumRatings) . "</a>"; } return "<span class='hastitle' title='" . join(", ", $a) . "'>" . join(" ", $b) . "</span>"; case self::FIELD_PAPERS: if (!$row->paperIds) { return ""; } $x = explode(",", $row->paperIds); sort($x, SORT_NUMERIC); foreach ($x as &$v) { $v = '<a href="' . hoturl("paper", "p={$v}") . '">' . $v . '</a>'; } $ls = "p/s/"; if ($this->limit == "auuns" || $this->limit == "all") { $ls = "p/all/"; } $ls = htmlspecialchars($ls . urlencode("au:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $x) . '</div>'; case self::FIELD_REVIEW_PAPERS: if (!$row->paperIds) { return ""; } $pids = explode(",", $row->paperIds); $rids = explode(",", $row->reviewIds); $ords = explode(",", $row->reviewOrdinals); $spids = $pids; sort($spids, SORT_NUMERIC); $m = array(); for ($i = 0; $i != count($pids); ++$i) { if ($ords[$i]) { $url = hoturl("paper", "p=" . $pids[$i] . "#r" . $pids[$i] . unparseReviewOrdinal($ords[$i])); } else { $url = hoturl("review", "p=" . $pids[$i] . "&r=" . $rids[$i]); } $m[$pids[$i]] = "<a href=\"{$url}\">" . $pids[$i] . "</a>"; } ksort($m, SORT_NUMERIC); $ls = htmlspecialchars("p/s/" . urlencode("re:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $m) . '</div>'; case self::FIELD_TAGS: if ($this->contact->isPC && ($tags = $row->viewable_tags($this->contact))) { $x = []; foreach (TagInfo::split($tags) as $t) { $x[] = '<a class="qq nw" href="' . hoturl("users", "t=%23" . TagInfo::base($t)) . '">' . $this->tagger->unparse_hashed($t) . '</a>'; } return join(" ", $x); } return ""; case self::FIELD_COLLABORATORS: if (!$this->contact->isPC || !($row->roles & Contact::ROLE_PC)) { return ""; } $t = array(); foreach (explode("\n", $row->collaborators) as $collab) { if (preg_match(',\\A(.*?)\\s*(\\(.*\\))\\s*\\z,', $collab, $m)) { $t[] = '<span class="nw">' . htmlspecialchars($m[1]) . ' <span class="auaff">' . htmlspecialchars($m[2]) . '</span></span>'; } else { if (($collab = trim($collab)) !== "" && strcasecmp($collab, "None")) { $t[] = '<span class="nw">' . htmlspecialchars($collab) . '</span>'; } } } return join("; ", $t); default: $f = ReviewForm::field($fieldId); if (!$f) { return ""; } if (!($row->roles & Contact::ROLE_PC) && !$this->contact->privChair && $this->limit != "req") { return ""; } $v = scoreCounts($row->{$fieldId}, $this->scoreMax[$fieldId]); $m = ""; if ($v->n > 0) { $m = $f->unparse_graph($v, 2, 0); } return $m; } }