assert_search_papers($user_chair, "NOT #fart", "9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30");
assert_search_papers($user_chair, "-#fart", "9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30");
// Check all tags
assert_search_papers($user_chair, "#none", "9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 26 27 28 29 30");
xassert_assign($Admin, false, "paper,tag\n9,~private\n10,~~chair\n");
assert_search_papers($user_chair, "#none", "11 12 14 15 16 18 19 20 21 22 23 24 25 26 27 28 29 30");
assert_search_papers($user_mgbaker, "#none", "3 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 26 27 28 29 30");
// comment searches
assert_search_papers($user_chair, "cmt:any", "1");
$comment2 = new CommentInfo(null, $paper18);
$c2ok = $comment2->save(array("text" => "test", "visibility" => "a", "blind" => false), $user_mgbaker);
xassert($c2ok);
assert_search_papers($user_chair, "cmt:any", "1 18");
assert_search_papers($user_chair, "cmt:any>1", "");
$comment3 = new CommentInfo(null, $paper18);
$c3ok = $comment3->save(array("text" => "test", "visibility" => "a", "blind" => false, "tags" => "redcmt"), $user_mgbaker);
xassert($c3ok);
assert_search_papers($user_chair, "cmt:any>1", "18");
assert_search_papers($user_chair, "cmt:jon", "");
assert_search_papers($user_chair, "cmt:mgbaker", "1 18");
assert_search_papers($user_chair, "cmt:mgbaker>1", "18");
assert_search_papers($user_chair, "cmt:#redcmt", "18");
/*$result = Dbl::qe("select paperId, tag, tagIndex from PaperTag order by paperId, tag");
$tags = array();
while ($result && ($row = $result->fetch_row()))
    $tags[] = "$row[0],$row[1],$row[2]\n";
echo join("", $tags);*/
// check review visibility for “not unless completed on same paper”
$Conf->save_setting("pc_seeallrev", Conf::PCSEEREV_IFCOMPLETE);
Contact::update_rights();
$paper2 = $Conf->paperRow(2, $user_chair);
function save_comment($text, $is_response, $roundnum)
{
    global $Me, $Conf, $prow, $crow;
    if ($crow) {
        $roundnum = (int) $crow->commentRound;
    }
    // If I have a review token for this paper, save under that anonymous user.
    $user = $Me;
    if ((!$crow || $crow->contactId != $Me->contactId) && ($cid = $Me->review_token_cid($prow)) && (!$crow || $crow->contactId == $cid)) {
        $user = Contact::find_by_id($cid);
    }
    $req = array("visibility" => @$_REQUEST["visibility"], "submit" => $is_response && @$_REQUEST["submitresponse"], "text" => $text, "tags" => @$_REQUEST["commenttags"], "blind" => @$_REQUEST["blind"]);
    if ($is_response && !$crow) {
        $cinfo = new CommentInfo((object) array("commentType" => COMMENTTYPE_RESPONSE, "commentRound" => $roundnum), $prow);
    } else {
        $cinfo = new CommentInfo($crow, $prow);
    }
    $ok = $cinfo->save($req, $user);
    $what = $is_response ? "Response" : "Comment";
    $confirm = false;
    if (!$ok && $is_response) {
        $crows = $Conf->comment_rows($Conf->comment_query("paperId={$prow->paperId} and (commentType&" . COMMENTTYPE_RESPONSE . ")!=0 and commentRound={$roundnum}"), $Me);
        reset($crows);
        $cur_response = @current($crows);
        if ($cur_response && $cur_response->comment == $text) {
            $cinfo = new CommentInfo($cur_response, $prow);
            $ok = true;
        } else {
            $confirm = Ht::xmsg("error", "A response was entered concurrently by another user. Reload to see it.");
        }
    }
    if (!$ok) {
        /* nada */
    } else {
        if ($is_response && (!$cinfo->commentId || $cinfo->commentType & COMMENTTYPE_DRAFT)) {
            if ($cinfo->commentId) {
                $confirm = 'Response saved. <strong>This draft response will not be shown to reviewers.</strong>';
            } else {
                $confirm = 'Response deleted.';
            }
            $isuf = $roundnum ? "_{$roundnum}" : "";
            if (($dl = $Conf->printableTimeSetting("resp_done{$isuf}")) != "N/A") {
                $confirm .= " You have until {$dl} to submit the response.";
            }
            $confirm = Ht::xmsg("warning", $confirm);
        } else {
            if ($is_response) {
                $rname = $Conf->resp_round_text($roundnum);
                $confirm = Ht::xmsg("confirm", ($rname ? "{$rname} response" : "Response") . ' submitted.');
            } else {
                if ($cinfo->commentId) {
                    $confirm = Ht::xmsg("confirm", "Comment saved.");
                } else {
                    $confirm = Ht::xmsg("confirm", "Comment deleted.");
                }
            }
        }
    }
    $j = array("ok" => $ok);
    if ($cinfo->commentId) {
        $j["cmt"] = $cinfo->unparse_json($Me);
    }
    if ($confirm) {
        $j["msg"] = $confirm;
    }
    $Conf->ajaxExit($j);
}