public function document_to_json($dtype, $docid)
 {
     global $Conf;
     if (!is_object($docid)) {
         $dresult = $Conf->document_result($this->paperid, $dtype, $docid);
         $drow = $Conf->document_row($dresult, $dtype);
         Dbl::free($dresult);
     } else {
         $drow = $docid;
         $docid = $drow ? $drow->paperStorageId : null;
     }
     $d = (object) array();
     if ($docid && !$this->hide_docids) {
         $d->docid = $docid;
     }
     if ($drow) {
         if ($drow->mimetype) {
             $d->mimetype = $drow->mimetype;
         }
         if ($drow->sha1 !== null && $drow->sha1 !== "") {
             $d->sha1 = bin2hex($drow->sha1);
         }
         if ($drow->timestamp) {
             $d->timestamp = (int) $drow->timestamp;
         }
         if (get($drow, "filename")) {
             $d->filename = $drow->filename;
         }
         $meta = null;
         if (isset($drow->infoJson) && is_object($drow->infoJson)) {
             $meta = $drow->infoJson;
         } else {
             if (isset($drow->infoJson) && is_string($drow->infoJson)) {
                 $meta = json_decode($drow->infoJson);
             }
         }
         if ($meta) {
             $d->metadata = $meta;
         }
         if ($this->export_content && $drow->docclass->load($drow)) {
             $d->content_base64 = base64_encode(Filer::content($drow));
         }
     }
     foreach ($this->document_callbacks as $cb) {
         call_user_func($cb, $d, $this->prow, $dtype, $drow);
     }
     if (!count(get_object_vars($d))) {
         $d = null;
     }
     return $d;
 }
Exemplo n.º 2
0
function _update_schema_regrade_flags(Conf $conf)
{
    $result = $conf->ql("select rgr.*, u.cid from RepositoryGradeRequest rgr\n        left join (select link, pset, min(cid) cid\n                   from ContactLink where type=" . LINK_REPO . " group by link, pset) u on (u.link=rgr.repoid)");
    while ($row = edb_orow($result)) {
        if ($row->cid && ($u = $conf->user_by_id($row->cid)) && ($pset = $conf->pset_by_id($row->pset))) {
            $info = new PsetView($pset, $u, $u);
            $info->force_set_commit($row->hash);
            $update = ["flags" => ["t" . $row->requested_at => ["uid" => $u->contactId]]];
            $info->update_current_info($update);
        }
    }
    Dbl::free($result);
    return true;
}
 public function __construct($user, $rounds = null)
 {
     global $Conf;
     $this->contact = $user;
     $qp = "select PaperReview.contactId, timeRequested, reviewSubmitted, reviewRound";
     if (!$this->contact->privChair) {
         $qp .= ", conflictType from PaperReview left join PaperConflict on (PaperConflict.paperId=PaperReview.paperId and PaperConflict.contactId=" . $this->contact->contactId . ")";
     } else {
         $qp .= ", 0 conflictType from PaperReview";
     }
     $qp .= " where reviewType>" . REVIEW_PC . " or (reviewType=" . REVIEW_PC . " and timeRequested>0 and reviewSubmitted>0)";
     if (!$this->contact->privChair) {
         $qp .= " and coalesce(conflictType,0)=0";
     }
     $qa = array();
     if ($rounds) {
         $qp .= " and reviewRound ?a";
         $qa[] = $rounds;
     }
     $result = Dbl::qe_apply($qp, $qa);
     while ($row = edb_row($result)) {
         $cid = (int) $row[4] ? "conflicts" : (int) $row[0];
         $this->r[$cid][] = array((int) $row[1], (int) $row[2], (int) $row[3]);
     }
     Dbl::free($result);
     foreach ($Conf->round_list() as $rn => $r) {
         $dl = $Conf->review_deadline($rn, true, false);
         $this->dl[$rn] = +$Conf->setting($dl);
     }
     // maybe hide who's who
     if (!$this->contact->can_view_aggregated_review_identity()) {
         $who = $r = array();
         foreach ($this->r as $cid => $data) {
             if ($cid === "conflicts" || $cid == $this->contact->contactId) {
                 $r[$cid] = $data;
             } else {
                 do {
                     $ncid = mt_rand(1, 10 * count(pcMembers()));
                 } while (isset($who[$ncid]));
                 $who[$ncid] = true;
                 $r["x" . $ncid] = $data;
             }
         }
         $this->r = $r;
     }
 }
function fix_one_delegation()
{
    global $Conf;
    $row = Dbl::fetch_first_row("select r.paperId, r.contactId, u.email, q.ct, q.cs, r.reviewNeedsSubmit\n            from PaperReview r\n            left join (select paperId, requestedBy, count(reviewId) ct, count(reviewSubmitted) cs\n                       from PaperReview where reviewType<" . REVIEW_SECONDARY . "\n                       group by paperId, requestedBy) q\n                on (q.paperId=r.paperId and q.requestedBy=r.contactId)\n            left join ContactInfo u on (u.contactId=r.contactId)\n            where r.reviewType=" . REVIEW_SECONDARY . " and r.reviewSubmitted is null\n            and if(coalesce(q.ct,0)=0,1,if(q.cs=0,-1,0))!=r.reviewNeedsSubmit\n            limit 1");
    if (!$row) {
        return false;
    }
    $pid = (int) $row[0];
    $req_cid = (int) $row[1];
    $req_email = $row[2];
    $prow = $Conf->paperRow(["paperId" => $pid], null);
    fwrite(STDERR, "Problem: #{$pid} review by {$req_email}\n");
    fwrite(STDERR, "  reviewNeedsSubmit {$row['5']}, " . plural($row[3] ?: 0, "delegate") . ", " . plural($row[4] ?: 0, "submitted delegate") . "\n");
    $result = Dbl::qe("select l.* from ActionLog l where paperId=? order by logId asc", $pid);
    $proposals = $confirmations = [];
    while ($row = edb_orow($result)) {
        if ($row->contactId == $req_cid && preg_match('/\\ALogged proposal for (\\S+) to review/', $row->action, $m) && ($xid = Contact::id_by_email($m[1]))) {
            $proposals[$xid] = true;
        } else {
            if (preg_match('/\\AAdded External review by (\\S+)/', $row->action, $m) && ($pc = pcByEmail($m[1])) && $pc->can_administer($prow)) {
                $confirmations[$row->contactId] = $pc->contactId;
            }
        }
    }
    Dbl::free($result);
    foreach ($proposals as $xid => $x) {
        if (isset($confirmations[$xid])) {
            $result1 = Dbl::qe("update PaperReview set requestedBy=? where paperId=? and contactId=? and requestedBy=?", $req_cid, $pid, $xid, $confirmations[$xid]);
            $result2 = Dbl::qe("update PaperReview r, PaperReview q set r.reviewNeedsSubmit=0 where r.paperId=? and r.contactId=? and q.paperId=? and q.contactId=? and q.reviewSubmitted is not null", $pid, $req_cid, $pid, $xid);
            if ($result1->affected_rows || $result2->affected_rows) {
                return true;
            }
        }
    }
    error_log("Failed to resolve paper #{$pid} review by {$req_email}");
    return false;
}
Exemplo n.º 5
0
 function load_grade()
 {
     if ($this->pset->gitless_grades) {
         $this->grade = $this->pset->contact_grade_for($this->user);
         $this->grade_notes = get($this->grade, "notes");
     } else {
         $this->repo_grade = null;
         if ($this->repo) {
             $result = $this->conf->qe("select rg.*, cn.hash, cn.notes, cn.notesversion\n                    from RepositoryGrade rg\n                    left join CommitNotes cn on (cn.hash=rg.gradehash and cn.pset=rg.pset)\n                    where rg.repoid=? and rg.pset=? and not rg.placeholder", $this->repo->repoid, $this->pset->psetid);
             $this->repo_grade = $result ? $result->fetch_object() : null;
             Dbl::free($result);
             if ($this->repo_grade && $this->repo_grade->notes) {
                 $this->repo_grade->notes = json_decode($this->repo_grade->notes);
             }
         }
         $this->grade = $this->repo_grade;
         $this->grade_notes = get($this->grade, "notes");
         if ($this->grade_notes && get($this->grade, "gradercid") && !get($this->grade_notes, "gradercid")) {
             $this->update_commit_info_at($this->grade->gradehash, ["gradercid" => $this->grade->gradercid]);
         }
         if (get($this->grade, "gradehash") && $this->commit === null) {
             // NB don't check recent_commits association here
             $this->commit = $this->grade->gradehash;
         }
     }
     $this->can_see_comments = $this->viewer->can_see_comments($this->pset, $this->user, $this);
     $this->can_see_grades = $this->viewer->can_see_grades($this->pset, $this->user, $this);
     $this->user_can_see_grades = $this->user->can_see_grades($this->pset, $this->user, $this);
 }
 private static function status_papers($status, $tracker, $acct)
 {
     global $Conf;
     $pids = array_slice($tracker->ids, $tracker->position, 3);
     $pc_conflicts = $acct->privChair || $acct->tracker_kiosk_state;
     $col = $j = "";
     if ($pc_conflicts) {
         $col = ", allconfs.conflictIds";
         $j = "left join (select paperId, group_concat(contactId) conflictIds from PaperConflict where paperId in (" . join(",", $pids) . ") group by paperId) allconfs on (allconfs.paperId=p.paperId)\n\t\t";
         $pcm = pcMembers();
     }
     $result = $Conf->qe("select p.paperId, p.title, p.paperFormat, p.leadContactId, p.managerContactId, r.reviewType, conf.conflictType{$col}\n            from Paper p\n            left join PaperReview r on (r.paperId=p.paperId and " . ($acct->contactId ? "r.contactId={$acct->contactId}" : "false") . ")\n            left join PaperConflict conf on (conf.paperId=p.paperId and " . ($acct->contactId ? "conf.contactId={$acct->contactId}" : "false") . ")\n            {$j}where p.paperId in (" . join(",", $pids) . ")");
     $papers = array();
     while ($row = PaperInfo::fetch($result, $acct)) {
         $papers[$row->paperId] = $p = (object) array();
         if (($acct->privChair || !$row->conflictType || !get($status, "hide_conflicts")) && $acct->tracker_kiosk_state != 1) {
             $p->pid = (int) $row->paperId;
             $p->title = $row->title;
             if ($format = $row->title_format()) {
                 $p->format = $format;
             }
         }
         if ($acct->contactId > 0 && $row->managerContactId == $acct->contactId) {
             $p->is_manager = true;
         }
         if ($row->reviewType) {
             $p->is_reviewer = true;
         }
         if ($row->conflictType) {
             $p->is_conflict = true;
         }
         if ($acct->contactId > 0 && $row->leadContactId == $acct->contactId) {
             $p->is_lead = true;
         }
         if ($pc_conflicts) {
             $p->pc_conflicts = array();
             foreach (explode(",", (string) $row->conflictIds) as $cid) {
                 if ($pc = get($pcm, $cid)) {
                     $p->pc_conflicts[$pc->sort_position] = (object) array("email" => $pc->email, "name" => Text::name_text($pc));
                 }
             }
             ksort($p->pc_conflicts);
             $p->pc_conflicts = array_values($p->pc_conflicts);
         }
     }
     Dbl::free($result);
     $status->papers = array();
     foreach ($pids as $pid) {
         $status->papers[] = $papers[$pid];
     }
 }
Exemplo n.º 7
0
 function find_snapshot($commit)
 {
     if (isset($this->_commitinfo[$commit])) {
         return $this->_commitinfo[$commit];
     }
     $this->analyze_snapshots();
     $bcommit = hex2bin(substr($commit, 0, strlen($commit) & ~1));
     if (strlen($bcommit) == 20) {
         $result = $this->conf->qe("select * from RepositoryCommitSnapshot where repoid=? and hash=?", $this->repoid, $bcommit);
     } else {
         $result = $this->conf->qe("select * from RepositoryCommitSnapshot where repoid=? and hash like '?ls%'", $this->repoid, $bcommit);
     }
     $match = null;
     while ($row = $result->fetch_object()) {
         $h = bin2hex($row->hash);
         if (str_starts_with($h, $commit)) {
             if ($match) {
                 $match = false;
                 break;
             }
             $match = $row;
         }
     }
     Dbl::free($result);
     if ($match) {
         $list = $this->commits_from_head("repo{$this->repoid}.snap" . gmstrftime("%Y%m%d.%H%M%S", $match->snapshot));
         $cinfo = $list[bin2hex($match->hash)];
         $cinfo->fromhead = "snapshot of " . strftime("%Y-%m-%d %H:%M:%S", $match->snapshot);
     } else {
         $cinfo = false;
     }
     $this->_commitinfo[$commit] = $cinfo;
     return $cinfo;
 }
Exemplo n.º 8
0
function show_regrades($result)
{
    global $Conf, $Me, $Now, $LastPsetFix;
    $rows = $uids = [];
    while ($row = edb_orow($result)) {
        $row->notes = json_decode($row->notes);
        $latest = "";
        $uid = 0;
        foreach (get($row->notes, "flags", []) as $t => $v) {
            if (!get($v, "resolved") && $t > $latest) {
                $latest = $t;
                $uid = get($v, "uid");
            }
        }
        if ($latest) {
            $rows[] = [$latest, $uid, $row];
            $uids[$uid] = true;
        }
    }
    Dbl::free($result);
    if (empty($rows)) {
        return;
    }
    usort($rows, function ($a, $b) {
        return strcmp($a[0], $b[0]);
    });
    $contacts = [];
    $result = $Conf->qe("select * from ContactInfo where contactId?a", array_keys($uids));
    while ($c = Contact::fetch($result, $Conf)) {
        $contacts[$c->contactId] = $c;
    }
    Dbl::free($result);
    echo '<div id="_regrades">';
    echo "<h3>flagged commits</h3>";
    echo '<table class="s61"><tbody>';
    $trn = 0;
    $checkbox = false;
    $sprefix = "";
    $reqsort = req("sort");
    $reqanonymize = req("anonymize");
    $pcmembers = pcMembers();
    foreach ($rows as $rowx) {
        $uid = $rowx[1];
        $row = $rowx[2];
        $u = $contacts[$uid];
        ++$trn;
        echo '<tr class="k', $trn % 2, '">';
        if ($checkbox) {
            echo '<td class="s61checkbox">', Ht::checkbox("s61_" . urlencode($Me->user_idpart($u)), 1, array("class" => "s61check")), '</td>';
        }
        echo '<td class="s61rownumber">', $trn, '.</td>';
        $pset = $Conf->pset_by_id($row->pset);
        echo '<td class="s61pset">', htmlspecialchars($pset->title), '</td>';
        echo '<td class="s61username">', '<a href="', hoturl("pset", ["pset" => $pset->urlkey, "u" => $Me->user_linkpart($u), "commit" => $row->hash, "sort" => $reqsort]), '">', htmlspecialchars($Me->user_linkpart($u)), '</a></td>', '<td class="s61hash"><a href="', hoturl("pset", array("pset" => $pset->urlkey, "u" => $Me->user_linkpart($u), "commit" => $row->hash, "sort" => $reqsort)), '">', substr($row->hash, 0, 7), '</a></td>';
        if (get($row->notes, "gradercid") || $row->main_gradercid) {
            $gcid = get($row->notes, "gradercid") ?: $row->main_gradercid;
            if (isset($pcmembers[$gcid])) {
                echo "<td>" . htmlspecialchars($pcmembers[$gcid]->firstName) . "</td>";
            } else {
                echo "<td>???</td>";
            }
        } else {
            echo "<td></td>";
        }
        echo "<td>";
        if ($row->hash === $row->gradehash) {
            echo "✱";
        }
        if ($row->haslinenotes) {
            echo "♪";
        }
        echo "</td>";
        $total = "";
        if ($row->notes) {
            $garr = render_grades($pset, $row->notes, null);
            if ($garr->totalindex !== null) {
                $total = $garr->all[$garr->totalindex];
            }
        }
        echo '<td class="r">' . $total . '</td>';
        echo '</tr>';
    }
    echo "</tbody></table></div>\n";
}
Exemplo n.º 9
0
function edb_orows($result)
{
    $x = array();
    while ($result && ($row = $result->fetch_object())) {
        $x[] = $row;
    }
    Dbl::free($result);
    return $x;
}
Exemplo n.º 10
0
 function commit_notes($hash)
 {
     assert(!$this->gitless);
     $result = $this->conf->qe("select * from CommitNotes where hash=? and pset=?", $hash, $this->psetid);
     $cn = edb_orow($result);
     if ($cn && $cn->notes) {
         $cn->notes = json_decode($cn->notes);
     }
     Dbl::free($result);
     return $cn;
 }
Exemplo n.º 11
0
 function save_logs($on)
 {
     if ($on && $this->_save_logs === false) {
         $this->_save_logs = array();
     } else {
         if (!$on && $this->_save_logs !== false) {
             $qs = [];
             foreach ($this->_save_logs as $cid_text => $pids) {
                 $pos = strpos($cid_text, "|");
                 $qs[] = self::format_log_query(substr($cid_text, $pos + 1), substr($cid_text, 0, $pos), array_keys($pids));
             }
             $mresult = Dbl::multi_q_raw(join(";", $qs));
             while ($result = $mresult->next()) {
                 Dbl::free($result);
             }
             $this->_save_logs = false;
         }
     }
 }
Exemplo n.º 12
0
 function _search()
 {
     global $Conf;
     if ($this->_matches === false) {
         return false;
     }
     assert($this->_matches === null);
     if ($this->limitName === "x") {
         $this->_matches = array();
         return true;
     }
     // parse and clean the query
     $qe = $this->_searchQueryType($this->q);
     //Conf::msg_info(Ht::pre_text(var_export($qe, true)));
     if (!$qe) {
         $qe = new SearchTerm("t");
     }
     // apply complex limiters (only current example: "acc" for non-chairs)
     $limit = $this->limitName;
     if ($limit === "acc" && !$this->privChair) {
         $qe = SearchTerm::make_op("and", array($qe, $this->_searchQueryWord("dec:yes", false)));
     }
     // apply review rounds (top down, needs separate step)
     if ($this->reviewAdjust) {
         $qe = $this->_query_adjust_reviews($qe, null);
         if ($this->_reviewAdjustError) {
             $this->warn("Unexpected use of “round:” or “rate:” ignored.  Stick to the basics, such as “re:reviewername round:roundname”.");
         }
     }
     //Conf::msg_info(Ht::pre_text(var_export($qe, true)));
     // collect clauses into tables, columns, and filters
     $sqi = new SearchQueryInfo();
     $sqi->add_table("Paper");
     $sqi->add_column("paperId", "Paper.paperId");
     // always include columns needed by rights machinery
     $sqi->add_column("timeSubmitted", "Paper.timeSubmitted");
     $sqi->add_column("timeWithdrawn", "Paper.timeWithdrawn");
     $sqi->add_column("outcome", "Paper.outcome");
     $filters = array();
     $this->_clauseTermSet($qe, $sqi, $filters);
     //Conf::msg_info(Ht::pre_text(var_export($filters, true)));
     // status limitation parts
     if ($limit === "rable") {
         $limitcontact = $this->_reviewer_fixed ? $this->reviewer() : $this->contact;
         if ($limitcontact->can_accept_review_assignment_ignore_conflict(null)) {
             $limit = $Conf->can_pc_see_all_submissions() ? "act" : "s";
         } else {
             if (!$limitcontact->isPC) {
                 $limit = "r";
             }
         }
     }
     if ($limit === "s" || $limit === "req" || $limit === "acc" || $limit === "und" || $limit === "unm" || $limit === "rable" && !$Conf->can_pc_see_all_submissions()) {
         $filters[] = "Paper.timeSubmitted>0";
     } else {
         if ($limit === "act" || $limit === "r" || $limit === "rable") {
             $filters[] = "Paper.timeWithdrawn<=0";
         } else {
             if ($limit === "unsub") {
                 $filters[] = "(Paper.timeSubmitted<=0 and Paper.timeWithdrawn<=0)";
             } else {
                 if ($limit === "lead") {
                     $filters[] = "Paper.leadContactId=" . $this->cid;
                 } else {
                     if ($limit === "manager") {
                         if ($this->privChair) {
                             $filters[] = "(Paper.managerContactId=" . $this->cid . " or Paper.managerContactId=0)";
                         } else {
                             $filters[] = "Paper.managerContactId=" . $this->cid;
                         }
                         $filters[] = "Paper.timeSubmitted>0";
                     }
                 }
             }
         }
     }
     // decision limitation parts
     if ($limit === "acc") {
         $filters[] = "Paper.outcome>0";
     } else {
         if ($limit === "und") {
             $filters[] = "Paper.outcome=0";
         }
     }
     // other search limiters
     if ($limit === "a") {
         $filters[] = $this->contact->actAuthorSql("PaperConflict");
         $this->needflags |= self::F_AUTHOR;
     } else {
         if ($limit === "r") {
             $filters[] = "MyReview.reviewType is not null";
             $this->needflags |= self::F_REVIEWER;
         } else {
             if ($limit === "ar") {
                 $filters[] = "(" . $this->contact->actAuthorSql("PaperConflict") . " or (Paper.timeWithdrawn<=0 and MyReview.reviewType is not null))";
                 $this->needflags |= self::F_AUTHOR | self::F_REVIEWER;
             } else {
                 if ($limit === "rout") {
                     $filters[] = "MyReview.reviewNeedsSubmit!=0";
                     $this->needflags |= self::F_REVIEWER;
                 } else {
                     if ($limit === "revs") {
                         $sqi->add_table("Limiter", array("join", "PaperReview"));
                     } else {
                         if ($limit === "req") {
                             $sqi->add_table("Limiter", array("join", "PaperReview", "Limiter.requestedBy={$this->cid} and Limiter.reviewType=" . REVIEW_EXTERNAL));
                         } else {
                             if ($limit === "unm") {
                                 $filters[] = "Paper.managerContactId=0";
                             }
                         }
                     }
                 }
             }
         }
     }
     // add common tables: conflicts, my own review, paper blindness
     if ($this->needflags & (self::F_MANAGER | self::F_NONCONFLICT | self::F_AUTHOR)) {
         $sqi->add_table("PaperConflict", array("left join", "PaperConflict", "PaperConflict.contactId={$this->cid}"));
         $sqi->add_column("conflictType", "PaperConflict.conflictType");
     }
     if ($this->needflags & self::F_REVIEWER) {
         if ($Conf->submission_blindness() == Conf::BLIND_OPTIONAL) {
             $sqi->add_column("paperBlind", "Paper.blind");
         }
         $qb = "";
         if ($tokens = $this->contact->review_tokens()) {
             $qb = " or MyReview.reviewToken in (" . join(",", $tokens) . ")";
         }
         $sqi->add_table("MyReview", array("left join", "PaperReview", "(MyReview.contactId={$this->cid}{$qb})"));
         $sqi->add_column("myReviewType", "MyReview.reviewType");
         $sqi->add_column("myReviewNeedsSubmit", "MyReview.reviewNeedsSubmit");
         $sqi->add_column("myReviewSubmitted", "MyReview.reviewSubmitted");
     }
     // check for annotated order
     $order_anno_tag = null;
     if ($qe->type !== "then" && ($sort = $qe->get_float("sort")) && ($tag = self::_check_sort_order_anno($sort))) {
         $dt = TagInfo::make_defined_tag($tag);
         if (count($dt->order_anno_list())) {
             $order_anno_tag = $dt;
         }
     }
     // add permissions tables if we will filter the results
     $need_filter = $this->needflags & self::F_XVIEW || $Conf->has_tracks() || $qe->type === "then" || $qe->get_float("heading") || $limit === "rable" || $order_anno_tag;
     if ($need_filter) {
         $sqi->add_rights_columns();
         if ($Conf->submission_blindness() == Conf::BLIND_OPTIONAL) {
             $sqi->add_column("paperBlind", "Paper.blind");
         }
     }
     // XXX some of this should be shared with paperQuery
     if ($need_filter && $Conf->has_track_tags() || get($this->_query_options, "tags") || $order_anno_tag) {
         $sqi->add_column("paperTags", "(select group_concat(' ', tag, '#', tagIndex separator '') from PaperTag where PaperTag.paperId=Paper.paperId)");
     }
     if (get($this->_query_options, "scores") || get($this->_query_options, "reviewTypes") || get($this->_query_options, "reviewContactIds")) {
         $j = "group_concat(contactId order by reviewId) reviewContactIds";
         $sqi->add_column("reviewContactIds", "R_submitted.reviewContactIds");
         if (get($this->_query_options, "reviewTypes")) {
             $j .= ", group_concat(reviewType order by reviewId) reviewTypes";
             $sqi->add_column("reviewTypes", "R_submitted.reviewTypes");
         }
         foreach (get($this->_query_options, "scores") ?: array() as $f) {
             $j .= ", group_concat({$f} order by reviewId) {$f}Scores";
             $sqi->add_column("{$f}Scores", "R_submitted.{$f}Scores");
         }
         $sqi->add_table("R_submitted", array("left join", "(select paperId, {$j} from PaperReview where reviewSubmitted>0 group by paperId)"));
     }
     // create query
     $q = "select ";
     foreach ($sqi->columns as $colname => $value) {
         $q .= $value . " " . $colname . ", ";
     }
     $q = substr($q, 0, strlen($q) - 2) . "\n    from ";
     foreach ($sqi->tables as $tabname => $value) {
         if (!$value) {
             $q .= $tabname;
         } else {
             $joiners = array("{$tabname}.paperId=Paper.paperId");
             for ($i = 2; $i < count($value); ++$i) {
                 $joiners[] = "(" . $value[$i] . ")";
             }
             $q .= "\n    " . $value[0] . " " . $value[1] . " as " . $tabname . " on (" . join("\n        and ", $joiners) . ")";
         }
     }
     if (count($filters)) {
         $q .= "\n    where " . join("\n        and ", $filters);
     }
     $q .= "\n    group by Paper.paperId";
     //Conf::msg_info(Ht::pre_text_wrap($q));
     // actually perform query
     $result = Dbl::qe_raw($q);
     if (!$result) {
         return $this->_matches = false;
     }
     $this->_matches = array();
     // correct query, create thenmap, groupmap, highlightmap
     $need_then = $qe->type === "then";
     $this->thenmap = null;
     if ($need_then && $qe->nthen > 1) {
         $this->thenmap = array();
     }
     $this->highlightmap = array();
     if ($need_filter) {
         $tag_order = [];
         while ($row = PaperInfo::fetch($result, $this->cid)) {
             if (!$this->contact->can_view_paper($row) || $limit === "rable" && !$limitcontact->can_accept_review_assignment_ignore_conflict($row)) {
                 $x = false;
             } else {
                 if ($need_then) {
                     $x = false;
                     for ($i = 0; $i < $qe->nthen && $x === false; ++$i) {
                         if ($this->_clauseTermCheck($qe->value[$i], $row)) {
                             $x = $i;
                         }
                     }
                 } else {
                     $x = !!$this->_clauseTermCheck($qe, $row);
                 }
             }
             if ($x === false) {
                 continue;
             }
             $this->_matches[] = $row->paperId;
             if ($this->thenmap !== null) {
                 $this->thenmap[$row->paperId] = $x;
             }
             if ($need_then) {
                 for ($j = $qe->nthen; $j < count($qe->value); ++$j) {
                     if ($this->_clauseTermCheck($qe->value[$j], $row) && $qe->highlights[$j - $qe->nthen] & 1 << $x) {
                         $this->highlightmap[$row->paperId] = $qe->highlight_types[$j - $qe->nthen] . "highlight";
                         break;
                     }
                 }
             }
             if ($order_anno_tag) {
                 if ($row->has_viewable_tag($order_anno_tag->tag, $this->contact)) {
                     $tag_order[] = [$row->paperId, $row->tag_value($order_anno_tag->tag)];
                 } else {
                     $tag_order[] = [$row->paperId, TAG_INDEXBOUND];
                 }
             }
         }
     } else {
         while ($row = $result->fetch_object()) {
             $this->_matches[] = (int) $row->paperId;
         }
     }
     Dbl::free($result);
     // add deleted papers explicitly listed by number (e.g. action log)
     if ($this->_allow_deleted) {
         $this->_add_deleted_papers($qe);
     }
     // view and sort information
     $this->viewmap = $qe->get_float("view", array());
     $this->sorters = array();
     $this->_add_sorters($qe, null);
     if ($qe->type === "then") {
         for ($i = 0; $i < $qe->nthen; ++$i) {
             $this->_add_sorters($qe->value[$i], $this->thenmap ? $i : null);
         }
     }
     $this->groupmap = [];
     if ($qe->type === "then") {
         for ($i = 0; $i < $qe->nthen; ++$i) {
             $h = $qe->value[$i]->get_float("heading");
             $this->groupmap[$i] = (object) ["heading" => $h, "annoFormat" => 0];
         }
     } else {
         if ($h = $qe->get_float("heading")) {
             $this->groupmap[0] = (object) ["heading" => $h, "annoFormat" => 0];
         } else {
             if ($order_anno_tag) {
                 $this->_assign_order_anno($order_anno_tag, $tag_order);
                 $this->is_order_anno = $order_anno_tag->tag;
             }
         }
     }
     // extract regular expressions and set _reviewer if the query is
     // about exactly one reviewer, and warn about contradictions
     $contradictions = array();
     $this->_queryExtractInfo($qe, true, false, $contradictions);
     foreach ($contradictions as $contradiction => $garbage) {
         $this->warn($contradiction);
     }
     // set $this->matchPreg from $this->regex
     if (!$this->overrideMatchPreg) {
         $this->matchPreg = array();
         foreach (array("ti" => "title", "au" => "authorInformation", "ab" => "abstract", "co" => "collaborators") as $k => $v) {
             if (isset($this->regex[$k]) && count($this->regex[$k])) {
                 $a = $b = array();
                 foreach ($this->regex[$k] as $x) {
                     $a[] = $x->preg_utf8;
                     if (isset($x->preg_raw)) {
                         $b[] = $x->preg_raw;
                     }
                 }
                 $x = (object) array("preg_utf8" => join("|", $a));
                 if (count($a) == count($b)) {
                     $x->preg_raw = join("|", $b);
                 }
                 $this->matchPreg[$v] = $x;
             }
         }
     }
     return true;
 }
Exemplo n.º 13
0
 function save_review($req, $rrow, $prow, $contact, &$tf = null)
 {
     global $Conf, $Opt;
     $newsubmit = @$req["ready"] && !@$req["unready"] && (!$rrow || !$rrow->reviewSubmitted);
     $submit = $newsubmit || $rrow && $rrow->reviewSubmitted;
     $admin = $contact->allow_administer($prow);
     if (!$contact->timeReview($prow, $rrow) && (!isset($req['override']) || !$admin)) {
         return Conf::msg_error("The <a href='" . hoturl("deadlines") . "'>deadline</a> for entering this review has passed." . ($admin ? "  Select the “Override deadlines” checkbox and try again if you really want to override the deadline." : ""));
     }
     $q = array();
     $diff_view_score = VIEWSCORE_FALSE;
     $wc = 0;
     foreach ($this->forder as $field => $f) {
         if (isset($req[$field]) && (!$f->round_mask || $f->is_round_visible($rrow))) {
             $fval = $req[$field];
             if ($f->has_options) {
                 if ($f->parse_is_empty($fval)) {
                     $fval = 0;
                 } else {
                     if (!($fval = $f->parse_value($fval, false))) {
                         continue;
                     }
                 }
             } else {
                 $fval = rtrim($fval);
                 if ($fval != "") {
                     $fval .= "\n";
                 }
                 // Check for valid UTF-8; re-encode from Windows-1252 or Mac OS
                 $fval = convert_to_utf8($fval);
                 if ($f->include_word_count()) {
                     $wc += count_words($fval);
                 }
             }
             if ($rrow && strcmp($rrow->{$field}, $fval) != 0 && strcmp(cleannl($rrow->{$field}), cleannl($fval)) != 0) {
                 $diff_view_score = max($diff_view_score, $f->view_score);
             }
             $q[] = "{$field}='" . sqlq($fval) . "'";
         }
     }
     // get the current time
     $now = time();
     if ($rrow && $rrow->reviewModified && $rrow->reviewModified > $now) {
         $now = $rrow->reviewModified + 1;
     }
     // potentially assign review ordinal (requires table locking since
     // mySQL is stupid)
     $locked = false;
     if ($newsubmit) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_AUTHOR);
         $q[] = "reviewSubmitted={$now}, reviewNeedsSubmit=0";
         if (!$rrow || !$rrow->reviewOrdinal) {
             $result = $Conf->qe("lock tables PaperReview write");
             if (!$result) {
                 return $result;
             }
             $locked = true;
             $result = $Conf->qe("select coalesce(max(reviewOrdinal), 0) from PaperReview where paperId={$prow->paperId} group by paperId");
             if ($result) {
                 $crow = edb_row($result);
                 $q[] = "reviewOrdinal=coalesce(reviewOrdinal, " . ($crow[0] + 1) . ")";
             }
             Dbl::free($result);
             $q[] = "timeDisplayed={$now}";
         }
     }
     // check whether used a review token
     $usedReviewToken = $contact->review_token_cid($prow, $rrow);
     // blind? reviewer type? edit version?
     $reviewBlind = $Conf->is_review_blind(!!@$req["blind"]);
     if ($rrow && $reviewBlind != $rrow->reviewBlind) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_ADMINONLY);
     }
     $q[] = "reviewBlind=" . ($reviewBlind ? 1 : 0);
     if ($rrow && $rrow->reviewType == REVIEW_EXTERNAL && $contact->contactId == $rrow->contactId && $contact->isPC && !$usedReviewToken) {
         $q[] = "reviewType=" . REVIEW_PC;
     }
     if ($rrow && $diff_view_score > VIEWSCORE_FALSE && isset($req["version"]) && ctype_digit($req["version"]) && $req["version"] > defval($rrow, "reviewEditVersion")) {
         $q[] = "reviewEditVersion=" . ($req["version"] + 0);
     }
     if ($diff_view_score > VIEWSCORE_FALSE && $Conf->sversion >= 98) {
         $q[] = "reviewWordCount=" . $wc;
     }
     if (isset($req["reviewFormat"]) && $Conf->sversion >= 104 && @$Opt["formatInfo"]) {
         $fmt = null;
         foreach ($Opt["formatInfo"] as $k => $f) {
             if (@$f["name"] && strcasecmp($f["name"], $req["reviewFormat"]) == 0) {
                 $fmt = (int) $k;
             }
         }
         if (!$fmt && $req["reviewFormat"] && preg_match('/\\A(?:plain\\s*)?(?:text)?\\z/i', $f["reviewFormat"])) {
             $fmt = 0;
         }
         $q[] = "reviewFormat=" . ($fmt === null ? "null" : $fmt);
     }
     // notification
     $notification_bound = $now - 10800;
     $notify = $notify_author = false;
     if (!$rrow || $diff_view_score > VIEWSCORE_FALSE) {
         $q[] = "reviewModified=" . $now;
         // do not notify on updates within 3 hours
         if ($submit && $diff_view_score > VIEWSCORE_ADMINONLY) {
             if (!$rrow || !$rrow->reviewNotified || $rrow->reviewNotified < $notification_bound) {
                 $q[] = $notify = "reviewNotified=" . $now;
             }
             if ((!$rrow || !$rrow->reviewAuthorNotified || $rrow->reviewAuthorNotified < $notification_bound) && $diff_view_score >= VIEWSCORE_AUTHOR && Contact::can_some_author_view_submitted_review($prow)) {
                 $q[] = $notify_author = "reviewAuthorNotified=" . $now;
             }
         }
     }
     // actually affect database
     if ($rrow) {
         $result = $Conf->qe("update PaperReview set " . join(", ", $q) . " where reviewId={$rrow->reviewId}");
         $reviewId = $rrow->reviewId;
         $contactId = $rrow->contactId;
     } else {
         $result = Dbl::qe_raw("insert into PaperReview set paperId={$prow->paperId}, contactId={$contact->contactId}, reviewType=" . REVIEW_PC . ", requestedBy={$contact->contactId}, reviewRound=" . $Conf->current_round() . ", " . join(", ", $q));
         $reviewId = $result ? $result->insert_id : null;
         $contactId = $contact->contactId;
     }
     // unlock tables even if problem
     if ($locked) {
         $Conf->qe("unlock tables");
     }
     if (!$result) {
         return $result;
     }
     // update caches
     Contact::update_rights();
     // look up review ID
     if (!$reviewId) {
         return $reviewId;
     }
     $req['reviewId'] = $reviewId;
     // log updates -- but not if review token is used
     if (!$usedReviewToken && $diff_view_score > VIEWSCORE_FALSE) {
         $text = "Review {$reviewId} ";
         if ($rrow && $contact->contactId != $rrow->contactId) {
             $text .= "by {$rrow->email} ";
         }
         $text .= $newsubmit ? "submitted" : ($submit ? "updated" : "saved draft");
         $contact->log_activity($text, $prow);
     }
     // potentially email chair, reviewers, and authors
     if ($submit) {
         $rrow = $Conf->reviewRow(["reviewId" => $reviewId]);
     }
     if ($submit && ($notify || $notify_author) && $rrow) {
         $tmpl = $newsubmit ? "@reviewsubmit" : "@reviewupdate";
         $submitter = $contact;
         if ($contactId != $submitter->contactId) {
             $submitter = Contact::find_by_id($contactId);
         }
         // construct mail
         $this->mailer_info = array("template" => $tmpl, "rrow" => $rrow, "reviewer_contact" => $submitter, "reviewNumber" => $prow->paperId . unparseReviewOrdinal($rrow->reviewOrdinal), "check_function" => "HotCRPMailer::check_can_view_review", "diff_view_score" => $diff_view_score);
         $this->mailer_preps = array();
         if ($Conf->timeEmailChairAboutReview()) {
             HotCRPMailer::send_manager($tmpl, $prow, $this->mailer_info);
         }
         $prow->notify(WATCHTYPE_REVIEW, array($this, "review_watch_callback"), $contact);
         if (count($this->mailer_preps)) {
             HotCRPMailer::send_combined_preparations($this->mailer_preps);
         }
         unset($this->mailer_info, $this->mailer_preps);
     }
     // if external, forgive the requestor from finishing their review
     if ($rrow && $rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy && $submit) {
         $Conf->q("update PaperReview set reviewNeedsSubmit=0 where paperId={$prow->paperId} and contactId={$rrow->requestedBy} and reviewType=" . REVIEW_SECONDARY . " and reviewSubmitted is null");
     }
     if ($tf !== null) {
         $what = "#{$prow->paperId}" . ($rrow && $rrow->reviewSubmitted ? unparseReviewOrdinal($rrow->reviewOrdinal) : "");
         if ($newsubmit) {
             $tf["newlySubmitted"][] = $what;
         } else {
             if ($diff_view_score > VIEWSCORE_FALSE && $submit) {
                 $tf["updated"][] = $what;
             } else {
                 if ($diff_view_score > VIEWSCORE_FALSE) {
                     $tf["savedDraft"][] = $what;
                 } else {
                     $tf["unchanged"][] = $what;
                 }
             }
         }
         if ($notify_author) {
             $tf["authorNotified"][] = $what;
         }
     }
     return $result;
 }
Exemplo n.º 14
0
 static function alltags_api($user, $qreq, $prow)
 {
     global $Conf;
     if (!$user->isPC) {
         json_exit(["ok" => false]);
     }
     $need_paper = $conflict_where = false;
     $where = $args = array();
     if ($user->allow_administer(null)) {
         $need_paper = true;
         if ($Conf->has_any_manager() && !$Conf->setting("tag_seeall")) {
             $conflict_where = "(p.managerContactId=0 or p.managerContactId={$user->contactId} or pc.conflictType is null)";
         }
     } else {
         if ($Conf->check_track_sensitivity(Track::VIEW)) {
             $where[] = "t.paperId ?a";
             $args[] = $user->list_submitted_papers_with_viewable_tags();
         } else {
             $need_paper = true;
             if ($Conf->has_any_manager() && !$Conf->setting("tag_seeall")) {
                 $conflict_where = "(p.managerContactId={$user->contactId} or pc.conflictType is null)";
             } else {
                 if (!$Conf->setting("tag_seeall")) {
                     $conflict_where = "pc.conflictType is null";
                 }
             }
         }
     }
     $q = "select distinct tag from PaperTag t";
     if ($need_paper) {
         $q .= " join Paper p on (p.paperId=t.paperId)";
         $where[] = "p.timeSubmitted>0";
     }
     if ($conflict_where) {
         $q .= " left join PaperConflict pc on (pc.paperId=t.paperId and pc.contactId={$user->contactId})";
         $where[] = $conflict_where;
     }
     $q .= " where " . join(" and ", $where);
     $tags = array();
     $result = Dbl::qe_apply($q, $args);
     while ($row = edb_row($result)) {
         $twiddle = strpos($row[0], "~");
         if ($twiddle === false || $twiddle == 0 && $row[0][1] === "~" && $user->privChair) {
             $tags[] = $row[0];
         } else {
             if ($twiddle > 0 && substr($row[0], 0, $twiddle) == $user->contactId) {
                 $tags[] = substr($row[0], $twiddle);
             }
         }
     }
     Dbl::free($result);
     json_exit(["ok" => true, "tags" => $tags]);
 }
Exemplo n.º 15
0
 public function run_discussion_order($tag, $sequential = false)
 {
     global $Conf;
     $this->mcmf_round_descriptor = "";
     $this->mcmf_optimizing_for = "Optimizing assignment";
     // load conflicts
     $cflt = array();
     foreach ($this->papersel as $pid) {
         $cflt[$pid] = array();
     }
     $result = Dbl::qe("select paperId, contactId from PaperConflict where paperId ?a and contactId ?a and conflictType>0", $this->papersel, array_keys($this->pcm));
     while ($row = edb_row($result)) {
         $cflt[(int) $row[0]][] = (int) $row[1];
     }
     Dbl::free($result);
     // run max-flow
     $result = $this->papersel;
     for ($roundno = 0; !$roundno || count($result) > 1; ++$roundno) {
         $this->mcmf_round_descriptor = $roundno ? ", round " . ($roundno + 1) : "";
         $result = $this->run_discussion_order_once($cflt, $result);
         if (!$roundno) {
             $groupmap = array();
             foreach ($result as $i => $pids) {
                 foreach ($pids as $pid) {
                     $groupmap[$pid] = $i;
                 }
             }
         }
     }
     // make assignments
     $this->set_progress("Completing assignment");
     $this->ass = array("paper,action,tag", "# hotcrp_assign_display_search", "# hotcrp_assign_show pcconf", "all,cleartag,{$tag}");
     $curgroup = -1;
     $index = 0;
     $search = array("HEADING:none");
     foreach ($result[0] as $pid) {
         if ($groupmap[$pid] != $curgroup && $curgroup != -1) {
             $search[] = "THEN HEADING:none";
         }
         $curgroup = $groupmap[$pid];
         $index += TagInfo::value_increment($sequential ? "aos" : "ao");
         $this->ass[] = "{$pid},tag,{$tag}#{$index}";
         $search[] = $pid;
     }
     $this->ass[1] = "# hotcrp_assign_display_search " . join(" ", $search);
     //global $Conf; $Conf->echoScript("$('#propass').before(" . json_encode(Ht::pre_text_wrap($m->debug_info(true) . "\n")) . ")");
 }
Exemplo n.º 16
0
 public function data()
 {
     global $Conf, $Me;
     // load data
     $paperIds = array_keys($this->papermap);
     $queryOptions = array("paperId" => $paperIds, "tags" => true);
     $this->fx->add_query_options($queryOptions, $Me);
     $this->fy->add_query_options($queryOptions, $Me);
     if ($this->fx->needs_review() || $this->fy->needs_review()) {
         $queryOptions["reviewOrdinals"] = true;
     }
     $result = Dbl::qe_raw($Conf->paperQuery($Me, $queryOptions));
     if ($this->type == self::CDF) {
         $data = $this->_cdf_data($result);
     } else {
         if ($this->type & self::BARCHART) {
             $data = $this->_combine_data($result);
         } else {
             $data = $this->_scatter_data($result);
         }
     }
     $this->_reviewer_reformat($data);
     $this->_revround_reformat($data);
     Dbl::free($result);
     return $data;
 }
Exemplo n.º 17
0
 public function save($sv, $si)
 {
     global $Conf;
     if ($sv->update("review_form", json_encode($this->nrfj))) {
         $rf = ReviewForm::get();
         $scoreModified = array();
         foreach ($this->nrfj as $fid => $fj) {
             if (get($fj, "position") && get($fj, "options")) {
                 $result = Dbl::qe_raw("update PaperReview set {$fid}=0 where {$fid}>" . count($fj->options));
                 if ($result && $result->affected_rows > 0) {
                     $scoreModified[] = htmlspecialchars($fj->name);
                 }
                 Dbl::free($result);
             }
         }
         foreach ($rf->fmap as $fid => $f) {
             foreach (self::$setting_prefixes as $fx) {
                 unset($sv->req["{$fx}{$fid}"]);
             }
         }
         if (count($scoreModified)) {
             $sv->set_warning(null, "Your changes invalidated some existing review scores.  The invalid scores have been reset to “Unknown”.  The relevant fields were: " . join(", ", $scoreModified) . ".");
         }
         $Conf->invalidateCaches(array("rf" => true));
         // reset all word counts in case author visibility changed
         Dbl::qe("update PaperReview set reviewWordCount=null");
     }
 }
Exemplo n.º 18
0
 public function fetch_comments($where)
 {
     $result = Dbl::qe("select PaperComment.*, firstName reviewFirstName, lastName reviewLastName, email reviewEmail\n            from PaperComment join ContactInfo on (ContactInfo.contactId=PaperComment.contactId)\n            where {$where} order by commentId");
     $comments = array();
     while ($c = CommentInfo::fetch($result, $this)) {
         $comments[$c->commentId] = $c;
     }
     Dbl::free($result);
     return $comments;
 }
Exemplo n.º 19
0
    fwrite(STDERR, "Need `_facefetch_script` configuration option or argument.\n");
    exit(1);
}
if (!isset($arg["limit"])) {
    $arg["limit"] = get($arg, "l");
}
$limit = (int) $arg["limit"];
$result = Dbl::qe("select contactId, email, huid from ContactInfo" . (isset($arg["all"]) || isset($arg["a"]) ? "" : " where contactImageId is null"));
$rows = array();
while ($row = edb_row($result)) {
    $rows[] = $row;
}
if ($limit) {
    shuffle($rows);
}
Dbl::free($result);
$n = $nworked = 0;
foreach ($rows as $row) {
    $url = $facefetch_urlpattern;
    if ($row[1] === null && strpos($url, '${EMAIL}') !== false || $row[2] === null && strpos($url, '${ID}') !== false) {
        continue;
    }
    $url = str_replace('${EMAIL}', urlencode($row[1]), $url);
    $url = str_replace('${ID}', urlencode($row[2]), $url);
    // fwrite(STDOUT, "$row[1] $fetchscript " . escapeshellarg($url) . " ");
    fwrite(STDOUT, "{$row['1']} ");
    $handle = popen($fetchscript . " " . escapeshellarg($url), "r");
    $data = stream_get_contents($handle);
    $status = pclose($handle);
    $content_type = "";
    if ($data && ($nl = strpos($data, "\n")) !== false) {
Exemplo n.º 20
0
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);
}
Exemplo n.º 21
0
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();
    }
}
Exemplo n.º 22
0
 private function reviewer_set()
 {
     if ($this->reviewer_set === false) {
         $this->reviewer_set = array();
         foreach (pcMembers() as $p) {
             $this->reviewer_set[$p->contactId] = $p;
         }
         $result = Dbl::qe("select " . AssignerContacts::$query . " from ContactInfo join PaperReview using (contactId) where (roles&" . Contact::ROLE_PC . ")=0 group by ContactInfo.contactId");
         while ($result && ($row = Contact::fetch($result))) {
             $this->reviewer_set[$row->contactId] = $row;
         }
         Dbl::free($result);
     }
     return $this->reviewer_set;
 }
Exemplo n.º 23
0
 private function load_by_query($where)
 {
     $result = $this->conf->q_raw("select ContactInfo.* from ContactInfo where {$where}");
     if ($row = $result ? $result->fetch_object() : null) {
         $this->merge($row);
     }
     Dbl::free($result);
     return !!$row;
 }
Exemplo n.º 24
0
 private static function try_list($opt, $listtype, $sort = null)
 {
     global $Conf, $Me;
     if ($listtype == "u" && $Me->privChair) {
         $searchtype = defval($opt, "t") === "all" ? "all" : "pc";
         $q = "select contactId from ContactInfo";
         if ($searchtype == "pc") {
             $q .= " where (roles&" . Contact::ROLE_PC . ")!=0";
         }
         $result = Dbl::ql("{$q} order by lastName, firstName, email");
         $a = array();
         while ($row = edb_row($result)) {
             $a[] = (int) $row[0];
         }
         Dbl::free($result);
         return self::create("u/" . $searchtype, $a, $searchtype == "pc" ? "Program committee" : "Users", hoturl_site_relative_raw("users", "t={$searchtype}"));
     } else {
         $search = new PaperSearch($Me, $opt);
         $x = $search->session_list_object($sort);
         if ($sort || $search->has_sort()) {
             $pl = new PaperList($search, array("sort" => $sort));
             $x->ids = $pl->id_array();
         }
         return $x;
     }
 }
Exemplo n.º 25
0
 function assign_review($pid, $reviewer_cid, $type, $extra = array())
 {
     global $Conf, $Now;
     $result = Dbl::qe("select reviewId, reviewType, reviewRound, reviewModified, reviewToken, requestedBy, reviewSubmitted from PaperReview where paperId=? and contactId=?", $pid, $reviewer_cid);
     $rrow = edb_orow($result);
     Dbl::free($result);
     $reviewId = $rrow ? $rrow->reviewId : 0;
     // can't delete a review that's in progress
     if ($type <= 0 && $rrow && $rrow->reviewType && $rrow->reviewModified) {
         if ($rrow->reviewType >= REVIEW_SECONDARY) {
             $type = REVIEW_PC;
         } else {
             return $reviewId;
         }
     }
     // change database
     if ($type > 0 && ($round = get($extra, "round_number")) === null) {
         $round = $Conf->current_round();
     }
     if ($type > 0 && (!$rrow || !$rrow->reviewType)) {
         $qa = "";
         if (get($extra, "mark_notify")) {
             $qa .= ", timeRequestNotified={$Now}";
         }
         if (get($extra, "token")) {
             $qa .= self::unassigned_review_token();
         }
         $new_requester_cid = $this->contactId;
         if ($new_requester = get($extra, "requester_contact")) {
             $new_requester_cid = $new_requester->contactId;
         }
         $q = "insert into PaperReview set paperId={$pid}, contactId={$reviewer_cid}, reviewType={$type}, reviewRound={$round}, timeRequested={$Now}{$qa}, requestedBy={$new_requester_cid}";
     } else {
         if ($type > 0 && ($rrow->reviewType != $type || $rrow->reviewRound != $round)) {
             $q = "update PaperReview set reviewType={$type}, reviewRound={$round}";
             if (!$rrow->reviewSubmitted) {
                 $q .= ", reviewNeedsSubmit=1";
             }
             $q .= " where reviewId={$reviewId}";
         } else {
             if ($type <= 0 && $rrow && $rrow->reviewType) {
                 $q = "delete from PaperReview where reviewId={$reviewId}";
             } else {
                 return $reviewId;
             }
         }
     }
     if (!($result = Dbl::qe_raw($q))) {
         return false;
     }
     if ($q[0] == "d") {
         $msg = "Removed " . ReviewForm::$revtype_names[$rrow->reviewType] . " review";
         $reviewId = 0;
     } else {
         if ($q[0] == "u") {
             $msg = "Changed " . ReviewForm::$revtype_names[$rrow->reviewType] . " review to " . ReviewForm::$revtype_names[$type];
         } else {
             $msg = "Added " . ReviewForm::$revtype_names[$type] . " review";
             $reviewId = $result->insert_id;
         }
     }
     $Conf->log($msg . " by " . $this->email, $reviewer_cid, $pid);
     // on new review, update PaperReviewRefused, ReviewRequest, delegation
     if ($q[0] == "i") {
         Dbl::ql("delete from PaperReviewRefused where paperId={$pid} and contactId={$reviewer_cid}");
         if ($req_email = get($extra, "requested_email")) {
             Dbl::qe("delete from ReviewRequest where paperId={$pid} and email=?", $req_email);
         }
         if ($type < REVIEW_SECONDARY) {
             self::update_review_delegation($pid, $new_requester_cid, 1);
         }
     } else {
         if ($q[0] == "d") {
             if ($rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy > 0) {
                 self::update_review_delegation($pid, $rrow->requestedBy, -1);
             }
         } else {
             if ($type == REVIEW_SECONDARY && $rrow->reviewType != REVIEW_SECONDARY && !$rrow->reviewSubmitted) {
                 self::update_review_delegation($pid, $reviewer_cid, 0);
             }
         }
     }
     // Mark rev_tokens setting for future update by update_rev_tokens_setting
     if ($rrow && get($rrow, "reviewToken") && $type <= 0) {
         $Conf->settings["rev_tokens"] = -1;
     }
     // Set pcrev_assigntime
     if ($q[0] == "i" && $type >= REVIEW_PC && $Conf->setting("pcrev_assigntime", 0) < $Now) {
         $Conf->save_setting("pcrev_assigntime", $Now);
     }
     Contact::update_rights();
     return $reviewId;
 }
Exemplo n.º 26
0
 function pc_members()
 {
     if ($this->_pc_members_cache === null) {
         $pc = $pca = array();
         $result = $this->q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where roles!=0 and (roles&" . Contact::ROLE_PCLIKE . ")!=0");
         $by_name_text = $by_first_text = [];
         $this->_pc_tags_cache = ["pc" => "pc"];
         while ($result && ($row = Contact::fetch($result, $this))) {
             $pca[$row->contactId] = $row;
             if ($row->roles & Contact::ROLE_PC) {
                 $pc[$row->contactId] = $row;
             }
             if ($row->firstName || $row->lastName) {
                 $name_text = Text::name_text($row);
                 if (isset($by_name_text[$name_text])) {
                     $row->nameAmbiguous = $by_name_text[$name_text]->nameAmbiguous = true;
                 }
                 $by_name_text[$name_text] = $row;
             }
             if ($row->firstName) {
                 if (isset($by_first_text[$row->firstName])) {
                     $row->firstNameAmbiguous = $by_first_text[$row->firstName]->firstNameAmbiguous = true;
                 }
                 $by_first_text[$row->firstName] = $row;
             }
             if ($row->contactTags) {
                 foreach (explode(" ", $row->contactTags) as $t) {
                     list($tag, $value) = TagInfo::split_index($t);
                     if ($tag) {
                         $this->_pc_tags_cache[strtolower($tag)] = $tag;
                     }
                 }
             }
         }
         Dbl::free($result);
         uasort($pc, "Contact::compare");
         $order = 0;
         foreach ($pc as $row) {
             $row->sort_position = $order;
             ++$order;
         }
         $this->_pc_members_cache = $pc;
         uasort($pca, "Contact::compare");
         $this->_pc_members_and_admins_cache = $pca;
         ksort($this->_pc_tags_cache);
     }
     return $this->_pc_members_cache;
 }
Exemplo n.º 27
0
 private static function load_optdata($pid)
 {
     $result = Dbl::qe("select optionId, value, data from PaperOption where paperId=?", $pid);
     $optdata = array();
     while ($row = edb_row($result)) {
         $optdata[$row[0] . "." . $row[1]] = $row[2];
     }
     Dbl::free($result);
     return $optdata;
 }
Exemplo n.º 28
0
if (!$Conf->dblink->multi_query(file_get_contents("{$ConfSitePATH}/src/schema.sql"))) {
    die_hard("* Can't reinitialize database.\n" . $Conf->dblink->error);
}
while ($Conf->dblink->more_results()) {
    Dbl::free($Conf->dblink->next_result());
}
// No setup phase.
$Conf->qe("delete from Settings where name='setupPhase'");
$Conf->load_settings();
// Contactdb.
if ($cdb = Contact::contactdb()) {
    if (!$cdb->multi_query(file_get_contents("{$ConfSitePATH}/test/cdb-schema.sql"))) {
        die_hard("* Can't reinitialize contact database.\n" . $cdb->error);
    }
    while ($cdb->more_results()) {
        Dbl::free($cdb->next_result());
    }
}
// Create initial administrator user.
$Admin = Contact::create(array("email" => "chair@_.com", "name" => "Jane Chair", "password" => "testchair"));
$Admin->save_roles(Contact::ROLE_ADMIN | Contact::ROLE_CHAIR | Contact::ROLE_PC, $Admin);
// Load data.
$json = json_decode(file_get_contents("{$ConfSitePATH}/test/db.json"));
if (!$json) {
    die_hard("* test/testdb.json error: " . json_last_error_msg() . "\n");
}
foreach ($json->contacts as $c) {
    $us = new UserStatus();
    if (!$us->save($c)) {
        die_hard("* failed to create user {$c->email}\n");
    }
Exemplo n.º 29
0
 private function _rows($field_list)
 {
     global $Conf;
     if (!$field_list) {
         return null;
     }
     // prepare query text
     $this->qopts["scores"] = array_keys($this->qopts["scores"]);
     if (empty($this->qopts["scores"])) {
         unset($this->qopts["scores"]);
     }
     $pq = $Conf->paperQuery($this->contact, $this->qopts);
     // make query
     $result = Dbl::qe_raw($pq);
     if (!$result) {
         return null;
     }
     // fetch rows
     $rows = array();
     while ($row = PaperInfo::fetch($result, $this->contact)) {
         $rows[$row->paperId] = $row;
     }
     // prepare review query (see also search > getfn == "reviewers")
     $this->review_list = array();
     if (isset($this->qopts["reviewList"]) && !empty($rows)) {
         $result = Dbl::qe("select Paper.paperId, reviewId, reviewType,\n                reviewSubmitted, reviewModified, reviewNeedsSubmit, reviewRound,\n                reviewOrdinal,\n                PaperReview.contactId, lastName, firstName, email\n                from Paper\n                join PaperReview using (paperId)\n                join ContactInfo on (PaperReview.contactId=ContactInfo.contactId)\n                where paperId?a", array_keys($rows));
         while ($row = edb_orow($result)) {
             Contact::set_sorter($row);
             $this->review_list[$row->paperId][] = $row;
         }
         foreach ($this->review_list as &$revlist) {
             usort($revlist, "PaperList::review_list_compar");
         }
         unset($revlist);
     }
     // prepare PC topic interests
     if (isset($this->qopts["allReviewerPreference"])) {
         $ord = 0;
         $pcm = pcMembers();
         foreach ($pcm as $pc) {
             $pc->prefOrdinal = sprintf("-0.%04d", $ord++);
             $pc->topicInterest = array();
         }
         $result = Dbl::qe("select contactId, topicId, " . $Conf->query_topic_interest() . " from TopicInterest");
         while ($row = edb_row($result)) {
             $pcm[$row[0]]->topicInterest[$row[1]] = $row[2];
         }
     }
     // analyze rows (usually noop)
     foreach ($field_list as $fdef) {
         $fdef->analyze($this, $rows);
     }
     // sort rows
     if (!empty($this->sorters)) {
         $rows = $this->_sort($rows);
         if (isset($this->qopts["allReviewScores"])) {
             $this->_sortReviewOrdinal($rows);
         }
     }
     // set `any->optID`
     if ($nopts = PaperOption::count_option_list()) {
         foreach ($rows as $prow) {
             foreach ($prow->options() as $o) {
                 if (!$this->any["opt{$o->id}"] && $this->contact->can_view_paper_option($prow, $o->option)) {
                     $this->any["opt{$o->id}"] = true;
                     --$nopts;
                 }
             }
             if (!$nopts) {
                 break;
             }
         }
     }
     Dbl::free($result);
     return $rows;
 }
Exemplo n.º 30
0
 function load_settings()
 {
     global $Opt, $OptOverride, $Now, $OK;
     // load settings from database
     $this->settings = array();
     $this->settingTexts = array();
     $this->_pc_seeall_cache = null;
     $this->deadlineCache = null;
     $result = $this->q("select name, value, data from Settings");
     while ($result && ($row = $result->fetch_row())) {
         $this->settings[$row[0]] = (int) $row[1];
         if ($row[2] !== null) {
             $this->settingTexts[$row[0]] = $row[2];
         }
         if (substr($row[0], 0, 4) == "opt.") {
             $okey = substr($row[0], 4);
             if (!array_key_exists($okey, $OptOverride)) {
                 $OptOverride[$okey] = @$Opt[$okey];
             }
             $Opt[$okey] = $row[2] === null ? $row[1] : $row[2];
         }
     }
     Dbl::free($result);
     // update schema
     if ($this->settings["allowPaperOption"] < 91) {
         require_once "updateschema.php";
         $oldOK = $OK;
         updateSchema($this);
         $OK = $oldOK;
     }
     $this->sversion = $this->settings["allowPaperOption"];
     // invalidate caches after loading from backup
     if (isset($this->settings["frombackup"]) && $this->invalidateCaches()) {
         $this->qe("delete from Settings where name='frombackup' and value=" . $this->settings["frombackup"]);
         unset($this->settings["frombackup"]);
     }
     // update options
     if (isset($Opt["ldapLogin"]) && !$Opt["ldapLogin"]) {
         unset($Opt["ldapLogin"]);
     }
     if (isset($Opt["httpAuthLogin"]) && !$Opt["httpAuthLogin"]) {
         unset($Opt["httpAuthLogin"]);
     }
     // set conferenceKey
     if (!isset($Opt["conferenceKey"])) {
         if (!isset($this->settingTexts["conf_key"]) && ($key = hotcrp_random_bytes(32)) !== false) {
             $this->save_setting("conf_key", 1, $key);
         }
         $Opt["conferenceKey"] = defval($this->settingTexts, "conf_key", "");
     }
     // set capability key
     if (!@$this->settings["cap_key"] && !@$Opt["disableCapabilities"] && !(($key = hotcrp_random_bytes(16)) !== false && ($key = base64_encode($key)) && $this->save_setting("cap_key", 1, $key))) {
         $Opt["disableCapabilities"] = true;
     }
     // GC old capabilities
     if ($this->sversion >= 58 && defval($this->settings, "__capability_gc", 0) < $Now - 86400) {
         foreach (array($this->dblink, Contact::contactdb()) as $db) {
             if ($db) {
                 Dbl::ql($db, "delete from Capability where timeExpires>0 and timeExpires<{$Now}");
                 Dbl::ql($db, "delete from CapabilityMap where timeExpires>0 and timeExpires<{$Now}");
             }
         }
         $this->q("insert into Settings (name, value) values ('__capability_gc', {$Now}) on duplicate key update value=values(value)");
         $this->settings["__capability_gc"] = $Now;
     }
     $this->crosscheck_settings();
     $this->crosscheck_options();
 }