public function json() { // find out who is light and who is heavy // (light => less than 0.66 * (80th percentile)) $nass = array(); foreach ($this->r as $cid => $x) { $nass[] = count($x); } sort($nass); $heavy_boundary = 0; if (count($nass)) { $heavy_boundary = 0.66 * $nass[(int) (0.8 * count($nass))]; } $contacts = pcMembers(); $need_contacts = []; foreach ($this->r as $cid => $x) { if (!isset($contacts[$cid]) && ctype_digit($cid)) { $need_contacts[] = $cid; } } if (count($need_contacts)) { $result = Dbl::q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where contactId ?a", $need_contacts); while ($result && ($row = Contact::fetch($result))) { $contacts[$row->contactId] = $row; } } $users = array(); $tags = $this->contact->can_view_reviewer_tags(); foreach ($this->r as $cid => $x) { if ($cid != "conflicts") { $users[$cid] = $u = (object) array(); $p = get($contacts, $cid); if ($p) { $u->name = Text::name_text($p); } if (count($x) < $heavy_boundary) { $u->light = true; } if ($p && $tags && ($t = $p->viewable_color_classes($this->contact))) { $u->color_classes = $t; } } } return (object) array("reviews" => $this->r, "deadlines" => $this->dl, "users" => $users); }
function pcMembers() { global $Conf, $Opt, $PcMembersCache; if (!@$PcMembersCache || $Conf->setting("pc") <= 0 || $PcMembersCache[0] < $Conf->setting("pc") || $PcMembersCache[1] != @$Opt["sortByLastName"]) { $pc = array(); $result = Dbl::q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where (roles&" . Contact::ROLE_PC . ")!=0"); $by_name_text = array(); $pctags = array("pc" => "pc"); while ($result && ($row = Contact::fetch($result))) { $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->contactTags) { foreach (explode(" ", $row->contactTags) as $t) { list($tag, $value) = TagInfo::split_index($t); if ($tag) { $pctags[strtolower($tag)] = $tag; } } } } uasort($pc, "Contact::compare"); ksort($pctags); $order = 0; foreach ($pc as $row) { $row->sort_position = $order; ++$order; } $PcMembersCache = array($Conf->setting("pc"), @$Opt["sortByLastName"], $pc, $pctags); } return $PcMembersCache[2]; }
function load_pset_info() { global $ConfSitePATH, $Conf, $PsetInfo, $PsetOverrides, $Opt; // read initial messages Messages::$main = new Messages(); $x = json_decode(file_get_contents("{$ConfSitePATH}/src/messages.json")); foreach ($x as $j) { Messages::$main->add($j); } // read psets $PsetInfo = load_psets_json(false); // parse psets foreach ($PsetInfo as $pk => $p) { if (!is_object($p) || !isset($p->psetid)) { continue; } object_merge_recursive($p, $PsetInfo->_defaults); try { $pset = new Pset($pk, $p); Pset::register($pset); } catch (Exception $exception) { // Want to give a good error message, so discover where the error is. // - create pset landmark object $locinfo = (object) array(); foreach (psets_json_data(false) as $fname => $data) { $x = Json::decode_landmarks($data, $fname); object_replace_recursive($locinfo, $x); } $locp = $locinfo->{$pk}; if (isset($locinfo->_defaults)) { object_merge_recursive($locp, $locinfo->_defaults); } // - lookup exception path in landmark object $path = $exception instanceof PsetConfigException ? $exception->path : array(); for ($pathpos = 0; $pathpos < count($path) && $locp && !is_string($locp); ++$pathpos) { $component = $path[$pathpos]; $locp = is_array($locp) ? $locp[$component] : $locp->{$component}; } // - report error if (is_object($locp) && @$locp->__LANDMARK__) { $locp = $locp->__LANDMARK__; } else { if (!is_string($locp)) { $locp = $locinfo->{$pk}->__LANDMARK__; } } Multiconference::fail_message($locp . ": Configuration error: " . $exception->getMessage()); } } // read message data if (!@$PsetInfo->_messagedefs) { $PsetInfo->_messagedefs = (object) array(); } if (!@$PsetInfo->_messagedefs->SYSTEAM) { $PsetInfo->_messagedefs->SYSTEAM = "cs61-staff"; } foreach ($PsetInfo->_messagedefs as $k => $v) { Messages::$main->define($k, $v); } // also create log/ and repo/ directories foreach (array("{$ConfSitePATH}/log", "{$ConfSitePATH}/repo") as $d) { if (!is_dir($d) && !mkdir($d, 02770, true)) { $e = error_get_last(); Multiconference::fail_message("`{$d}` missing and cannot be created (" . $e["message"] . ")."); } if (!file_exists("{$d}/.htaccess") && ($x = file_get_contents("{$ConfSitePATH}/src/.htaccess")) !== false && file_put_contents("{$d}/.htaccess", $x) != strlen($x)) { Multiconference::fail_message("Error creating `{$d}/.htaccess`"); } } // if any anonymous problem sets, create anonymous usernames foreach (Pset::$all as $p) { if (!$p->disabled && $p->anonymous) { while ($row = Dbl::fetch_first_row(Dbl::qe("select contactId from ContactInfo where anon_username is null limit 1"))) { Dbl::q("update ContactInfo set anon_username='******' where contactId=?", $row[0]); } } } }
private function load_by_id($cid) { $result = Dbl::q("select ContactInfo.* from ContactInfo where contactId=?", $cid); if ($row = $result ? $result->fetch_object() : null) { $this->merge($row); } Dbl::free($result); return !!$row; }
static function find_by_id($cid) { $result = Dbl::q("select ContactInfo.* from ContactInfo where contactId=" . (int) $cid); return self::fetch($result); }
public function save($sv, $si) { global $Conf; if ($si->name == "tag_vote" && $sv->has_savedv("tag_vote")) { // check allotments $pcm = pcMembers(); foreach (preg_split('/\\s+/', $sv->savedv("tag_vote")) as $t) { if ($t === "") { continue; } $base = substr($t, 0, strpos($t, "#")); $allotment = substr($t, strlen($base) + 1); $result = Dbl::q("select paperId, tag, tagIndex from PaperTag where tag like '%~" . sqlq_for_like($base) . "'"); $pvals = array(); $cvals = array(); $negative = false; while ($row = edb_row($result)) { $who = substr($row[1], 0, strpos($row[1], "~")); if ($row[2] < 0) { $sv->set_error(null, "Removed " . Text::user_html($pcm[$who]) . "’s negative “{$base}” vote for paper #{$row['0']}."); $negative = true; } else { $pvals[$row[0]] = defval($pvals, $row[0], 0) + $row[2]; $cvals[$who] = defval($cvals, $who, 0) + $row[2]; } } foreach ($cvals as $who => $what) { if ($what > $allotment) { $sv->set_error("tag_vote", Text::user_html($pcm[$who]) . " already has more than {$allotment} votes for tag “{$base}”."); } } $q = $negative ? " or (tag like '%~" . sqlq_for_like($base) . "' and tagIndex<0)" : ""; $Conf->qe("delete from PaperTag where tag='" . sqlq($base) . "'{$q}"); $q = array(); foreach ($pvals as $pid => $what) { $q[] = "({$pid}, '" . sqlq($base) . "', {$what})"; } if (count($q) > 0) { $Conf->qe("insert into PaperTag values " . join(", ", $q)); } } } if ($si->name == "tag_approval" && $sv->has_savedv("tag_approval")) { $pcm = pcMembers(); foreach (preg_split('/\\s+/', $sv->savedv("tag_approval")) as $t) { if ($t === "") { continue; } $result = $Conf->q("select paperId, tag, tagIndex from PaperTag where tag like '%~" . sqlq_for_like($t) . "'"); $pvals = array(); $negative = false; while ($row = edb_row($result)) { $who = substr($row[1], 0, strpos($row[1], "~")); if ($row[2] < 0) { $sv->set_error(null, "Removed " . Text::user_html($pcm[$who]) . "’s negative “{$t}” approval vote for paper #{$row['0']}."); $negative = true; } else { $pvals[$row[0]] = defval($pvals, $row[0], 0) + 1; } } $q = $negative ? " or (tag like '%~" . sqlq_for_like($t) . "' and tagIndex<0)" : ""; $Conf->qe("delete from PaperTag where tag='" . sqlq($t) . "'{$q}"); $q = array(); foreach ($pvals as $pid => $what) { $q[] = "({$pid}, '" . sqlq($t) . "', {$what})"; } if (count($q) > 0) { $Conf->qe("insert into PaperTag values " . join(", ", $q)); } } } TagInfo::invalidate_defined_tags(); }
function initialize_paper_columns() { global $Conf; PaperColumn::register(new SelectorPaperColumn("sel", array("minimal" => true))); PaperColumn::register(new SelectorPaperColumn("selon", array("minimal" => true, "className" => "pl_sel"))); PaperColumn::register(new SelectorPaperColumn("selconf", array("className" => "pl_confselector"))); PaperColumn::register(new SelectorPaperColumn("selunlessconf", array("minimal" => true, "className" => "pl_sel"))); PaperColumn::register(new IdPaperColumn()); PaperColumn::register(new TitlePaperColumn()); PaperColumn::register(new StatusPaperColumn("status", false)); PaperColumn::register(new StatusPaperColumn("statusfull", true)); PaperColumn::register(new ReviewerTypePaperColumn("revtype")); PaperColumn::register(new ReviewStatusPaperColumn()); PaperColumn::register(new ReviewSubmittedPaperColumn()); PaperColumn::register(new ReviewDelegationPaperColumn()); PaperColumn::register(new AssignReviewPaperColumn()); PaperColumn::register(new TopicScorePaperColumn()); PaperColumn::register(new TopicListPaperColumn()); PaperColumn::register(new PreferencePaperColumn("pref", false)); PaperColumn::register_synonym("revpref", "pref"); PaperColumn::register(new PreferenceListPaperColumn("allpref", false)); PaperColumn::register_synonym("allrevpref", "allpref"); PaperColumn::register(new PreferenceListPaperColumn("alltopicpref", true)); PaperColumn::register_synonym("allrevtopicpref", "alltopicpref"); PaperColumn::register(new DesirabilityPaperColumn()); PaperColumn::register(new ReviewerListPaperColumn()); PaperColumn::register(new AuthorsPaperColumn()); PaperColumn::register(new CollabPaperColumn()); PaperColumn::register_synonym("co", "collab"); PaperColumn::register(new TagListPaperColumn(false)); PaperColumn::register(new SearchOptsPaperColumn()); PaperColumn::register(new AbstractPaperColumn()); PaperColumn::register(new LeadPaperColumn()); PaperColumn::register(new ShepherdPaperColumn()); PaperColumn::register(new PCConflictListPaperColumn()); PaperColumn::register(new ConflictMatchPaperColumn("authorsmatch", "authorInformation")); PaperColumn::register(new ConflictMatchPaperColumn("collabmatch", "collaborators")); PaperColumn::register(new TimestampPaperColumn()); PaperColumn::register(new FoldAllPaperColumn()); PaperColumn::register_factory("tag:", new TagPaperColumn(null, null, false)); PaperColumn::register_factory("tagval:", new TagPaperColumn(null, null, true)); PaperColumn::register_factory("opt:", new OptionPaperColumn(null)); PaperColumn::register_factory("#", new TagPaperColumn(null, null, null)); PaperColumn::register_factory("pref:", new PreferencePaperColumn(null, false)); if (PaperOption::count_option_list()) { PaperColumn::register_factory("", new OptionPaperColumn(null)); } foreach (ReviewForm::all_fields() as $f) { if ($f->has_options) { PaperColumn::register_factory("", new ScorePaperColumn(null)); break; } } if ($Conf && $Conf->setting("formulas")) { $result = Dbl::q("select * from Formula order by lower(name)"); while ($result && ($row = Formula::fetch($result))) { $fid = $row->formulaId; FormulaPaperColumn::register(new FormulaPaperColumn("formula{$fid}", $row)); } } PaperColumn::register_factory("", new FormulaPaperColumn("", null)); $tagger = new Tagger(); if ($Conf && (TagInfo::has_vote() || TagInfo::has_approval() || TagInfo::has_rank())) { $vt = array(); foreach (TagInfo::defined_tags() as $v) { if ($v->vote || $v->approval || $v->rank) { $vt[] = $v->tag; } } foreach ($vt as $n) { TagReportPaperColumn::register(new TagReportPaperColumn($n)); } } }
// scorechart.php -- HotCRP chart generator // HotCRP is Copyright (c) 2006-2016 Eddie Kohler and Regents of the UC // Distributed under an MIT-like license; see LICENSE // Generates a PNG image of a bar chat. // Arguments are passed in as v; s is graph style. // Don't forget to change the width and height calculations in // ReviewField::unparse_graph if you change the width and height here. if (!isset($_REQUEST["v"])) { header("HTTP/1.0 400 Bad Request"); exit; } // fail if no GD support so the browser displays alt text if (!function_exists("imagecreate")) { require_once "src/init.php"; Dbl::q("insert into Settings set name='__gd_required', value=1 on duplicate key update value=1"); header("HTTP/1.0 503 Service Unavailable"); exit; } // parse values $s = isset($_REQUEST["s"]) ? $_REQUEST["s"] : 0; $valMax = 1; $values = array(); $maxY = $sum = 0; foreach (explode(",", $_REQUEST["v"]) as $value) { $value = ctype_digit($value) && $value > 0 ? intval($value) : 0; $values[$valMax++] = $value; $maxY = max($value, $maxY); $sum += $value; } if (isset($_REQUEST["h"]) && is_numeric($_REQUEST["h"])) {
public function load_content($doc) { global $Conf; $ok = false; $result = null; if (!opt("dbNoPapers") && get_i($doc, "paperStorageId") > 1) { $result = Dbl::q("select paper, compression from PaperStorage where paperStorageId=" . $doc->paperStorageId); } if (!$result || !($row = edb_row($result)) || $row[0] === null) { $doc->content = ""; } else { if ($row[1] == 1) { $doc->content = gzinflate($row[0]); $ok = true; } else { $doc->content = $row[0]; $ok = true; } } if (!$ok && ($s3 = self::s3_document()) && ($filename = self::s3_filename($doc))) { $filename = self::s3_filename($doc); $content = $s3->load($filename); if ($content !== "" && $content !== null) { $doc->content = $content; $ok = true; } else { if ($s3->status != 200) { error_log("S3 error: GET {$filename}: {$s3->status} {$s3->status_text} " . json_encode($s3->response_headers)); } } } if (!$ok) { $num = get($doc, "paperId") ? " #{$doc->paperId}" : ""; $doc->error = true; if ($this->dtype == DTYPE_SUBMISSION) { $doc->error_text = "Paper{$num} has not been uploaded."; } else { if ($this->dtype == DTYPE_FINAL) { $doc->error_text = "Paper{$num}’s final copy has not been uploaded."; } } } $doc->size = strlen($doc->content); $this->store_filestore($doc, true); // silently does nothing if error || !filestore return $ok; }
function document_row($result, $dtype = DTYPE_SUBMISSION) { if (!($doc = edb_orow($result))) { return $doc; } // type doesn't matter if ($dtype === null && isset($doc->documentType)) { $dtype = $doc->documentType = (int) $doc->documentType; } $doc->docclass = new HotCRPDocument($dtype); // in modern versions sha1 is set at storage time; before it wasn't if ($doc->paperStorageId > 1 && $doc->sha1 == "" && $doc->docclass->load_content($doc)) { $doc->sha1 = sha1($doc->content, true); Dbl::q("update PaperStorage set sha1=? where paperStorageId=?", $doc->sha1, $doc->paperStorageId); } // unparse infoJson if ($doc->infoJson) { $doc->infoJson_str = $doc->infoJson; $doc->infoJson = json_decode($doc->infoJson); } return $doc; }
function expandvar_generic($what, $isbool) { global $Conf, $Opt; if ($what == "%REVIEWDEADLINE%") { if ($this->row && @$this->row->reviewType > 0) { $rev = $this->row->reviewType >= REVIEW_PC ? "pc" : "ext"; } else { if ($this->row && isset($this->row->roles)) { $rev = $this->row->roles & Contact::ROLE_PCLIKE ? "pc" : "ext"; } else { if ($Conf->setting("pcrev_soft") != $Conf->setting("extrev_soft")) { if ($isbool && $Conf->setting("pcrev_soft") > 0 == $Conf->setting("extrev_soft") > 0) { return $Conf->setting("pcrev_soft") > 0; } else { return $isbool ? null : $what; } } else { $rev = "ext"; } } } $what = "%DEADLINE(" . $rev . "rev_soft)%"; } $len = strlen($what); if ($len > 12 && substr($what, 0, 10) == "%DEADLINE(" && substr($what, $len - 2) == ")%") { $inner = substr($what, 10, $len - 12); if ($isbool) { return $Conf->setting($inner) > 0; } else { return $Conf->printableTimeSetting($inner); } } if (($what == "%NUMACCEPTED%" || $what == "%NUMSUBMITTED%") && $this->_statistics === null) { $this->_statistics = array(0, 0); $result = Dbl::q("select outcome, count(paperId) from Paper where timeSubmitted>0 group by outcome"); while ($row = edb_row($result)) { $this->_statistics[0] += $row[1]; if ($row[0] > 0) { $this->_statistics[1] += $row[1]; } } } if ($what == "%NUMSUBMITTED%") { return $this->_statistics[0]; } if ($what == "%NUMACCEPTED%") { return $this->_statistics[1]; } if ($what == "%CONTACTDBDESCRIPTION%") { return get($Opt, "contactdb_description") ?: "HotCRP"; } if (preg_match('/\\A%(OTHER|REQUESTER|REVIEWER)(CONTACT|NAME|EMAIL|FIRST|LAST)%\\z/', $what, $m)) { if ($m[1] === "REVIEWER") { $x = $this->_expand_reviewer($m[2], $isbool); if ($x !== false || $isbool) { return $x; } } else { if ($c = $this->contacts[strtolower($m[1])]) { return $this->expand_user($c, $m[2]); } else { if ($isbool) { return false; } } } } if ($what == "%AUTHORVIEWCAPABILITY%" && @$Opt["disableCapabilities"]) { return ""; } return self::EXPANDVAR_CONTINUE; }