if ($asstype && $row->conflictType > 0) {
                                    $conflicts[] = $row->paperId;
                                } else {
                                    if ($asstype && $row->reviewType >= REVIEW_PC && $asstype != $row->reviewType) {
                                        $assigned[] = $row->paperId;
                                    } else {
                                        $user->assign_review($row->paperId, $pc->contactId, $asstype);
                                        $nworked++;
                                    }
                                }
                            }
                            if (count($conflicts)) {
                                Conf::msg_error("Some papers were not assigned because of conflicts (" . join(", ", $conflicts) . ").  If these conflicts are in error, remove them and try to assign again.");
                            }
                            if (count($assigned)) {
                                Conf::msg_error("Some papers were not assigned because the PC member already had an assignment (" . join(", ", $assigned) . ").");
                            }
                            if ($nworked) {
                                $Conf->confirmMsg($asstype == 0 ? "Unassigned reviews." : "Assigned reviews.");
                            }
                            Dbl::qe_raw("unlock tables");
                            $Conf->update_rev_tokens_setting(false);
                        }
                    }
                }
            }
        }
    }
}
SearchAction::register("assign", null, SiteLoader::API_POST | SiteLoader::API_PAPER, new Assign_SearchAction());
<?php

// sa/sa_mail.php -- HotCRP helper classes for search actions
// HotCRP is Copyright (c) 2006-2016 Eddie Kohler and Regents of the UC
// Distributed under an MIT-like license; see LICENSE
class Mail_SearchAction extends SearchAction
{
    function allow(Contact $user)
    {
        return $user->is_manager() && Navigation::page() !== "reviewprefs";
    }
    function list_actions(Contact $user, $qreq, PaperList $plist, &$actions)
    {
        $actions[] = [1000, "mail", "Mail", "<b>:</b> &nbsp;" . Ht::select("recipients", array("au" => "Contact authors", "rev" => "Reviewers"), $qreq->recipients, ["class" => "wantcrpfocus"]) . " &nbsp;" . Ht::submit("fn", "Go", ["value" => "mail", "onclick" => "return plist_submit.call(this)", "data-plist-submit-all" => 1])];
    }
    function run(Contact $user, $qreq, $ssel)
    {
        $r = in_array($qreq->recipients, ["au", "rev"]) ? $qreq->recipients : "all";
        if ($ssel->equals_search(new PaperSearch($user, $qreq))) {
            $x = "q=" . urlencode($qreq->q) . "&plimit=1";
        } else {
            $x = "p=" . join("+", $ssel->selection());
        }
        go(hoturl("mail", $x . "&t=" . urlencode($qreq->t) . "&recipients={$r}"));
    }
}
SearchAction::register("mail", null, SiteLoader::API_GET | SiteLoader::API_PAPER, new Mail_SearchAction());
        while ($prow = PaperInfo::fetch($result, $user)) {
            if ($user->can_administer($prow, true)) {
                $pj[$prow->paperId] = $ps->paper_json($prow);
            } else {
                $pj[$prow->paperId] = (object) ["pid" => $prow->paperId, "error" => "You don’t have permission to administer this paper."];
                if ($this->iszip) {
                    $this->zipdoc->warnings[] = "#{$prow->paperId}: You don’t have permission to administer this paper.";
                }
            }
        }
        $pj = array_values($ssel->reorder($pj));
        if (count($pj) == 1) {
            $pj = $pj[0];
            $pj_filename = $Opt["downloadPrefix"] . "paper" . $ssel->selection_at(0) . "-data.json";
        } else {
            $pj_filename = $Opt["downloadPrefix"] . "data.json";
        }
        if ($this->iszip) {
            $this->zipdoc->add(json_encode($pj, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n", $pj_filename);
            $this->zipdoc->download();
        } else {
            header("Content-Type: application/json");
            header("Content-Disposition: attachment; filename=" . mime_quote_string($pj_filename));
            echo json_encode($pj, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
        }
        exit;
    }
}
SearchAction::register("get", "json", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetJson_SearchAction(false));
SearchAction::register("get", "jsonattach", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetJson_SearchAction(true));
            }
        }
        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);
            }
        }
    }
}
SearchAction::register("tag", null, SiteLoader::API_POST | SiteLoader::API_PAPER, new Tag_SearchAction());
    function run(Contact $user, $qreq, $ssel)
    {
        global $Conf;
        $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection(), "topics" => 1)));
        $texts = array();
        $tmap = $Conf->topic_map();
        while ($row = PaperInfo::fetch($result, $user)) {
            if ($user->can_view_paper($row)) {
                $out = array();
                foreach ($row->topics() as $t) {
                    $out[] = [$row->paperId, $row->title, $tmap[$t]];
                }
                if (!count($out)) {
                    $out[] = [$row->paperId, $row->title, "<none>"];
                }
                arrayappend($texts[$row->paperId], $out);
            }
        }
        downloadCSV($ssel->reorder($texts), array("paper", "title", "topic"), "topics");
    }
}
SearchAction::register("get", null, SiteLoader::API_GET | SiteLoader::API_PAPER, new Get_SearchAction());
SearchAction::register("get", "paper", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetDocument_SearchAction(DTYPE_SUBMISSION));
SearchAction::register("get", "final", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetDocument_SearchAction(DTYPE_FINAL));
SearchAction::register("get", "checkformat", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetCheckFormat_SearchAction());
SearchAction::register("get", "abstract", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetAbstract_SearchAction());
SearchAction::register("get", "authors", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetAuthors_SearchAction());
SearchAction::register("get", "contact", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetContacts_SearchAction());
SearchAction::register("get", "pcconf", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetPcconflicts_SearchAction());
SearchAction::register("get", "topics", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetTopics_SearchAction());
        $actions[] = [900, "decide", "Decide", "<b>:</b> Set to &nbsp;" . decisionSelector($qreq->decision, null, " class=\"wantcrpfocus\"") . " &nbsp;" . Ht::submit("fn", "Go", ["value" => "decide", "onclick" => "return plist_submit.call(this)"])];
    }
    function run(Contact $user, $qreq, $ssel)
    {
        global $Conf;
        $o = cvtint($qreq->decision);
        $decision_map = $Conf->decision_map();
        if ($o === null || !isset($decision_map[$o])) {
            return Conf::msg_error("Bad decision value.");
        }
        $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection())));
        $success = $fails = array();
        while ($prow = PaperInfo::fetch($result, $user)) {
            if ($user->can_set_decision($prow, true)) {
                $success[] = $prow->paperId;
            } else {
                $fails[] = "#" . $prow->paperId;
            }
        }
        if (count($fails)) {
            Conf::msg_error("You cannot set paper decisions for " . pluralx($fails, "paper") . " " . commajoin($fails) . ".");
        }
        if (count($success)) {
            Dbl::qe("update Paper set outcome={$o} where paperId ?a", $success);
            $Conf->update_paperacc_setting($o > 0);
            redirectSelf(array("atab" => "decide", "decision" => $o));
        }
    }
}
SearchAction::register("decide", null, SiteLoader::API_POST | SiteLoader::API_PAPER, new Decide_SearchAction());
    {
        global $Conf;
        if ($Conf->has_any_lead_or_shepherd()) {
            $actions[] = [491 - $this->islead, $this->subname, "Reviews", $this->islead ? "Discussion leads" : "Shepherds"];
        }
    }
    function run(Contact $user, $qreq, $ssel)
    {
        global $Conf;
        $type = $this->islead ? "lead" : "shepherd";
        $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection(), "reviewerName" => $type)));
        $texts = array();
        while ($row = PaperInfo::fetch($result, $user)) {
            if ($row->reviewEmail && ($this->islead ? $user->can_view_lead($row, true) : $user->can_view_shepherd($row, true))) {
                arrayappend($texts[$row->paperId], [$row->paperId, $row->title, $row->reviewFirstName, $row->reviewLastName, $row->reviewEmail]);
            }
        }
        downloadCSV($ssel->reorder($texts), array("paper", "title", "first", "last", "{$type}email"), "{$type}s");
    }
}
SearchAction::register("get", "pcassignments", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetPcassignments_SearchAction());
SearchAction::register("get", "revform", SiteLoader::API_GET, new GetReviewForm_SearchAction(false));
SearchAction::register("get", "revformz", SiteLoader::API_GET, new GetReviewForm_SearchAction(true));
SearchAction::register("get", "rev", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetReviews_SearchAction(false));
SearchAction::register("get", "revz", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetReviews_SearchAction(true));
SearchAction::register("get", "scores", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetScores_SearchAction());
SearchAction::register("get", "votes", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetVotes_SearchAction());
SearchAction::register("get", "rank", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetRank_SearchAction());
SearchAction::register("get", "lead", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetLead_SearchAction(true));
SearchAction::register("get", "shepherd", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetLead_SearchAction(false));
            }
            $conflicts = $prow->conflicts();
            foreach ($pcm as $cid => $p) {
                $pref = $prow->reviewer_preference($p);
                $conf = get($conflicts, $cid);
                $tv = $prow->topicIds ? $prow->topic_interest_score($p) : 0;
                if ($pref || $conf || $tv) {
                    $texts[$prow->paperId][] = array("paper" => $prow->paperId, "title" => $prow->title, "first" => $p->firstName, "last" => $p->lastName, "email" => $p->email, "preference" => $pref[0] ?: "", "expertise" => unparse_expertise($pref[1]), "topic_score" => $tv ?: "", "conflict" => $conf ? "conflict" : "");
                    $has_conflict = $has_conflict || $conf;
                    $has_expertise = $has_expertise || $pref[1] !== null;
                    $has_topic_score = $has_topic_score || $tv;
                }
            }
        }
        $headers = array("paper", "title", "first", "last", "email", "preference");
        if ($has_expertise) {
            $headers[] = "expertise";
        }
        if ($has_topic_score) {
            $headers[] = "topic_score";
        }
        if ($has_conflict) {
            $headers[] = "conflict";
        }
        downloadCSV($ssel->reorder($texts), $headers, "allprefs", ["selection" => true]);
    }
}
SearchAction::register("get", "revpref", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetRevpref_SearchAction(false));
SearchAction::register("get", "revprefx", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetRevpref_SearchAction(true));
SearchAction::register("get", "allrevpref", SiteLoader::API_GET | SiteLoader::API_PAPER, new GetAllRevpref_SearchAction());