function saveTagIndexes($tag, $filename, &$settings, &$titles, &$linenos, &$errors) { global $Conf, $Me, $Error; $result = $Conf->qe($Conf->paperQuery($Me, array("paperId" => array_keys($settings)))); while ($row = PaperInfo::fetch($result, $Me)) { if ($settings[$row->paperId] !== null && !$Me->can_change_tag($row, $tag, null, 1)) { $errors[$linenos[$row->paperId]] = "You cannot rank paper #{$row->paperId}."; unset($settings[$row->paperId]); } else { if ($titles[$row->paperId] !== "" && strcmp($row->title, $titles[$row->paperId]) != 0 && strcasecmp($row->title, simplify_whitespace($titles[$row->paperId])) != 0) { $errors[$linenos[$row->paperId]] = "Warning: Title doesn’t match"; } } } if (!$tag) { defappend($Error["tags"], "No tag defined"); } else { if (count($settings)) { $x = array("paper,tag,lineno"); foreach ($settings as $pid => $value) { $x[] = "{$pid},{$tag}#" . ($value === null ? "clear" : $value) . "," . $linenos[$pid]; } $assigner = new AssignmentSet($Me); $assigner->parse(join("\n", $x) . "\n", $filename); $assigner->report_errors(); $assigner->execute(); } } $settings = $titles = $linenos = array(); }
function complete_assignment($callback) { global $Me; $assignset = new AssignmentSet($Me, false); $assignset->parse($_POST["file"], get($_POST, "filename"), assignment_defaults(), $callback); $SSel = SearchSelection::make(make_qreq(), $Me); $assignset->restrict_papers($SSel->selection()); return $assignset->execute(true); }
$review2e = fetch_review(2, $user_external); xassert(!$user_mgbaker->can_view_review($paper2, $review2e, false)); $review2e = save_review(2, $user_external, $revreq); $review2d = fetch_review(2, $user_mgbaker); xassert(!$review2d->reviewSubmitted); xassert($review2d->reviewNeedsSubmit == 0); xassert($user_mgbaker->can_view_review($paper2, $review2a, false)); xassert($user_mgbaker->can_view_review($paper2, $review2e, false)); // complex assignments assert_search_papers($user_chair, "2 AND re:4", "2"); assert_search_papers($user_chair, "re:mgbaker", "1 2 13 17"); assert_search_papers($user_chair, "re:sec:mgbaker", "2"); assert_search_papers($user_chair, "sec:mgbaker", "2"); assert_search_papers($user_chair, "re:pri:mgbaker", "1 13 17"); $assignset = new AssignmentSet($user_chair, null); $assignset->parse("action,paper,email,reviewtype\nreview,all,mgbaker@cs.stanford.edu,secondary:primary\n"); xassert_eqq(join("\n", $assignset->errors_text()), ""); xassert($assignset->execute()); xassert(AssignmentSet::run($user_chair, "action,paper,email,reviewtype\nreview,all,mgbaker@cs.stanford.edu,secondary:primary\n")); assert_search_papers($user_chair, "re:sec:mgbaker", ""); assert_search_papers($user_chair, "re:pri:mgbaker", "1 2 13 17"); $review2d = fetch_review(2, $user_mgbaker); xassert(!$review2d->reviewSubmitted); xassert($review2d->reviewNeedsSubmit == 1); xassert(AssignmentSet::run($user_chair, "action,paper,email,reviewtype\nreview,2,mgbaker@cs.stanford.edu,primary:secondary\n")); assert_search_papers($user_chair, "re:sec:mgbaker", "2"); assert_search_papers($user_chair, "re:pri:mgbaker", "1 13 17"); $review2d = fetch_review(2, $user_mgbaker); xassert(!$review2d->reviewSubmitted); xassert($review2d->reviewNeedsSubmit == 0); // uploading the current assignment makes no changes
function xassert_assign($who, $override, $what) { $assignset = new AssignmentSet($who, $override); $assignset->parse($what); xassert($assignset->execute()); }
public static function run($contact, $text, $forceShow = null) { $aset = new AssignmentSet($contact, $forceShow); $aset->parse($text); return $aset->execute(); }
Conf::msg_error("Only administrators can delete users."); } else { if ($Acct->contactId == $Me->contactId) { Conf::msg_error("You aren’t allowed to delete yourself."); } else { if ($Acct->has_database_account()) { $tracks = databaseTracks($Acct->contactId); if (count($tracks->soleAuthor)) { Conf::msg_error("This user can’t be deleted since they are sole contact for " . pluralx($tracks->soleAuthor, "paper") . " " . textArrayPapers($tracks->soleAuthor) . ". You will be able to delete the user after deleting those papers or adding additional paper contacts."); } else { foreach (array("ContactInfo", "PaperComment", "PaperConflict", "PaperReview", "PaperReviewPreference", "PaperReviewRefused", "PaperWatch", "ReviewRating", "TopicInterest") as $table) { $Conf->qe("delete from {$table} where contactId={$Acct->contactId}"); } // delete twiddle tags $assigner = new AssignmentSet($Me, true); $assigner->parse("paper,tag\nall,{$Acct->contactId}~all#clear\n"); $assigner->execute(); // clear caches if ($Acct->isPC || $Acct->privChair) { $Conf->invalidateCaches(array("pc" => 1)); } // done $Conf->confirmMsg("Permanently deleted user " . htmlspecialchars($Acct->email) . "."); $Me->log_activity("Permanently deleted user " . htmlspecialchars($Acct->email) . " ({$Acct->contactId})"); go(hoturl("users", "t=all")); } } } } } function value($key, $value)
private function result_html() { global $Conf, $Me, $Qreq, $SSel, $pcsel; $assignments = $this->autoassigner->assignments(); ReviewAssigner::$prefinfo = $this->autoassigner->prefinfo; ob_start(); if (!$assignments) { $Conf->warnMsg("Nothing to assign."); return ob_get_clean(); } $assignset = new AssignmentSet($Me, true); $assignset->parse(join("\n", $assignments)); list($atypes, $apids) = $assignset->types_and_papers(true); $badpairs_inputs = $badpairs_arg = array(); for ($i = 1; $i <= 20; ++$i) { if ($Qreq["bpa{$i}"] && $Qreq["bpb{$i}"]) { array_push($badpairs_inputs, Ht::hidden("bpa{$i}", $Qreq["bpa{$i}"]), Ht::hidden("bpb{$i}", $Qreq["bpb{$i}"])); $badpairs_arg[] = $Qreq["bpa{$i}"] . "-" . $Qreq["bpb{$i}"]; } } echo Ht::form_div(hoturl_post("autoassign", ["saveassignment" => 1, "assigntypes" => join(" ", $atypes), "assignpids" => join(" ", $apids), "xbadpairs" => count($badpairs_arg) ? join(" ", $badpairs_arg) : null, "profile" => $Qreq->profile, "XDEBUG_PROFILE" => $Qreq->XDEBUG_PROFILE, "seed" => $Qreq->seed])); $atype = $assignset->type_description(); echo "<h3>Proposed " . ($atype ? $atype . " " : "") . "assignment</h3>"; Conf::msg_info("Select “Apply changes” if this looks OK. (You can always alter the assignment afterwards.) Reviewer preferences, if any, are shown as “P#”."); $assignset->report_errors(); $assignset->echo_unparse_display(); // print preference unhappiness if ($Qreq->profile && $this->atype_review) { $umap = $this->autoassigner->pc_unhappiness(); sort($umap); echo '<p style="font-size:65%">Preference unhappiness: '; $usum = 0; foreach ($umap as $u) { $usum += $u; } if (count($umap) % 2 == 0) { $umedian = ($umap[count($umap) / 2 - 1] + $umap[count($umap) / 2]) / 2; } else { $umedian = $umap[(count($umap) - 1) / 2]; } echo 'mean ', sprintf("%.2f", $usum / count($umap)), ', min ', $umap[0], ', 10% ', $umap[(int) (count($umap) * 0.1)], ', 25% ', $umap[(int) (count($umap) * 0.25)], ', median ', $umedian, ', 75% ', $umap[(int) (count($umap) * 0.75)], ', 90% ', $umap[(int) (count($umap) * 0.9)], ', max ', $umap[count($umap) - 1], '<br/>Time: ', sprintf("%.6f", microtime(true) - $this->start_at); foreach ($this->autoassigner->profile as $name => $time) { echo ', ', sprintf("%s %.6f", htmlspecialchars($name), $time); } echo '</p>'; } echo "<div class='g'></div>", "<div class='aahc'><div class='aa'>\n", Ht::submit("submit", "Apply changes"), "\n ", Ht::submit("download", "Download assignment file"), "\n ", Ht::submit("cancel", "Cancel"), "\n"; foreach (array("t", "q", "a", "revtype", "revaddtype", "revpctype", "cleartype", "revct", "revaddct", "revpcct", "pctyp", "balance", "badpairs", "rev_roundtag", "method", "haspap") as $t) { if (isset($Qreq[$t])) { echo Ht::hidden($t, $Qreq[$t]); } } echo Ht::hidden("pcs", join(" ", array_keys($pcsel))), join("", $badpairs_inputs), Ht::hidden("p", join(" ", $SSel->selection())), "\n"; // save the assignment echo Ht::hidden("assignment", join("\n", $assignments)), "\n"; echo "</div></div></div></form>"; return ob_get_clean(); }
function run(Contact $user, $qreq, $ssel) { global $Conf; $papers = $ssel->selection(); $act = $qreq->tagfn; $tagreq = trim(str_replace(",", " ", (string) $qreq->tag)); $tags = preg_split('/\\s+/', $tagreq); if ($act == "da") { $otags = $tags; foreach ($otags as $t) { $tags[] = "all~" . preg_replace(',\\A.*~([^~]+)\\z', '$1', $t); } $act = "d"; } else { if ($act == "sor") { shuffle($papers); } } $x = array("action,paper,tag\n"); if ($act == "s" || $act == "so" || $act == "sos" || $act == "sor") { foreach ($tags as $t) { $x[] = "cleartag,all," . TagInfo::base($t) . "\n"; } } if ($act == "s" || $act == "a") { $action = "tag"; } else { if ($act == "d") { $action = "cleartag"; } else { if ($act == "so" || $act == "sor" || $act == "ao") { $action = "nexttag"; } else { if ($act == "sos" || $act == "aos") { $action = "seqnexttag"; } else { $action = null; } } } } $assignset = new AssignmentSet($user, $user->privChair); if (count($papers) && $action) { foreach ($papers as $p) { foreach ($tags as $t) { $x[] = "{$action},{$p},{$t}\n"; } } $assignset->parse(join("", $x)); } else { if (count($papers) && $act == "cr" && $user->privChair) { $source_tag = trim((string) $qreq->tagcr_source); if ($source_tag == "") { $source_tag = substr($tagreq, 0, 2) == "~~" ? substr($tagreq, 2) : $tagreq; } $tagger = new Tagger($user); if ($tagger->check($tagreq, Tagger::NOPRIVATE | Tagger::NOVALUE) && $tagger->check($source_tag, Tagger::NOPRIVATE | Tagger::NOCHAIR | Tagger::NOVALUE)) { $r = new PaperRank($source_tag, $tagreq, $papers, $qreq->tagcr_gapless, "Search", "search"); $r->run($qreq->tagcr_method); $r->apply($assignset); $assignset->finish(); if ($qreq->q === "") { $qreq->q = "order:{$tagreq}"; } } else { $assignset->error($tagger->error_html); } } } if ($errors = join("<br />\n", $assignset->errors_html())) { if ($assignset->has_assigners()) { Conf::msg_warning("Some tag assignments were ignored:<br />\n{$errors}"); $assignset->clear_errors(); } else { Conf::msg_error($errors); } } $success = $assignset->execute(); if (!$Conf->headerPrinted && $qreq->ajax) { $Conf->ajaxExit(array("ok" => $success)); } else { if (!$Conf->headerPrinted && $success) { if (!$errors) { $Conf->confirmMsg("Tags saved."); } $args = array("atab" => "tag"); foreach (array("tag", "tagfn", "tagcr_method", "tagcr_source", "tagcr_gapless") as $arg) { if (isset($qreq[$arg])) { $args[$arg] = $qreq[$arg]; } } redirectSelf($args); } } }
static function settags_api($user, $qreq, $prow) { global $Conf; if ($qreq->cancelsettags) { json_exit(["ok" => true]); } if ($prow && !$user->can_view_paper($prow)) { json_exit(["ok" => false, "error" => "No such paper."]); } // save tags using assigner $x = array("paper,action,tag"); if ($prow) { if (isset($qreq->tags)) { $x[] = "{$prow->paperId},tag,all#clear"; foreach (TagInfo::split($qreq->tags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t); } } foreach (TagInfo::split((string) $qreq->addtags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t); } foreach (TagInfo::split((string) $qreq->deltags) as $t) { $x[] = "{$prow->paperId},tag," . CsvGenerator::quote($t . "#clear"); } } else { if (isset($qreq->tagassignment)) { $pids = []; $pid = -1; foreach (preg_split('/[\\s,]+/', $qreq->tagassignment) as $w) { if ($w !== "" && ctype_digit($w)) { $pid = intval($w); } else { if ($w !== "" && $pid > 0) { $x[] = "{$pid},tag," . CsvGenerator::quote($w); $pids[$pid] = true; } } } } } $assigner = new AssignmentSet($user, $user->is_admin_force()); $assigner->parse(join("\n", $x)); $error = join("<br />", $assigner->errors_html()); $ok = $assigner->execute(); // exit if ($ok && $prow) { $prow->load_tags(); $treport = self::tagreport($user, $prow); if ($treport->warnings) { $Conf->warnMsg(join("<br>", $treport->warnings)); } $taginfo = (object) ["ok" => true, "pid" => $prow->paperId]; $prow->add_tag_info_json($taginfo, $user); json_exit($taginfo, true); } else { if ($ok) { $p = []; $result = Dbl::qe_raw($Conf->paperQuery($user, ["paperId" => array_keys($pids), "tags" => true])); while ($prow = PaperInfo::fetch($result, $user)) { $p[$prow->paperId] = (object) []; $prow->add_tag_info_json($p[$prow->paperId], $user); } json_exit(["ok" => true, "p" => $p]); } else { json_exit(["ok" => false, "error" => $error], true); } } }