public function delete($capdata) { assert(!$capdata || is_string($capdata->salt)); if ($capdata) { Dbl::ql($this->dblink, "delete from Capability where salt=?", $capdata->salt); } }
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; } }
function createAnonymousReview() { global $Conf, $Me, $Now, $prow, $rrows; Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write, ContactInfo write, PaperConflict read, ActionLog write"); // find an unassigned anonymous review contact $contactemail = unassignedAnonymousContact(); $result = Dbl::qe_raw("select contactId from ContactInfo where email='" . sqlq($contactemail) . "'"); if (edb_nrows($result) == 1) { $row = edb_row($result); $reqId = $row[0]; } else { $result = Dbl::qe("insert into ContactInfo set firstName='Jane Q.', lastName='Public', unaccentedName='Jane Q. Public', email=?, affiliation='Unaffiliated', password='', disabled=1, creationTime={$Now}", $contactemail); if (!$result) { return $result; } $reqId = $result->insert_id; } // store the review request $reviewId = $Me->assign_review($prow->paperId, $reqId, REVIEW_EXTERNAL, array("mark_notify" => true, "token" => true)); if ($reviewId) { $result = Dbl::ql("select reviewToken from PaperReview where reviewId={$reviewId}"); $row = edb_row($result); $Conf->confirmMsg("Created a new anonymous review for paper #{$prow->paperId}. The review token is " . encode_token((int) $row[0]) . "."); } Dbl::qx_raw("unlock tables"); $Conf->update_rev_tokens_setting(true); return true; }
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; }
public function mark_activity() { global $Now; if (!$this->activity_at || $this->activity_at < $Now) { $this->activity_at = $Now; if ($this->contactId && !$this->is_anonymous_user()) { $this->conf->ql("update ContactInfo set lastLogin={$Now} where contactId={$this->contactId}"); } if ($this->contactDbId) { Dbl::ql(self::contactdb(), "update ContactInfo set activity_at={$Now} where contactDbId={$this->contactDbId}"); } } }
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(); } }
Dbl::free($result); } if ($papers) { $result = Dbl::ql(Contact::contactdb(), "select confid from Conferences where `dbname`=?", $Opt["dbName"]); $row = Dbl::fetch_first_row($result); if (!$row) { fwrite(STDERR, "Conference is not recored in contactdb\n"); exit(1); } $confid = $row[0]; $result = Dbl::ql($Conf->dblink, "select paperId, title from Paper"); $q = array(); while ($row = edb_row($result)) { $q[] = "(" . $confid . "," . $row[0] . ",'" . sqlq($row[1]) . "')"; } Dbl::free($result); for ($i = 0; $i < count($q); $i += 25) { $xq = array_slice($q, $i, 25); Dbl::ql_raw(Contact::contactdb(), "insert into ConferencePapers (confid,paperId,title) values " . join(",", $xq) . " on duplicate key update title=values(title)"); } } if ($collaborators) { $result = Dbl::ql($Conf->dblink, "select email, collaborators, updateTime, lastLogin from ContactInfo where collaborators is not null and collaborators!=''"); while ($row = edb_row($result)) { $time = (int) $row[2] ?: (int) $row[3]; if ($time > 0) { Dbl::ql(Contact::contactdb(), "update ContactInfo set collaborators=?, updateTime=? where email=? and (collaborators is null or collaborators='' or updateTime<?)", $row[1], $time, $row[0], $time); } } Dbl::free($result); }
public function delete($capdata) { if ($capdata) { Dbl::ql($this->dblink, "delete from Capability where capabilityId=" . $capdata->capabilityId); } }
function updateSchema($Conf) { global $Opt, $OK; // avoid error message abut timezone, set to $Opt // (which might be overridden by database values later) if (function_exists("date_default_timezone_set") && isset($Opt["timezone"]) && $Opt["timezone"]) { date_default_timezone_set($Opt["timezone"]); } while (($result = Dbl::ql("insert into Settings set name='__schema_lock', value=1 on duplicate key update value=1")) && $result->affected_rows == 0) { time_nanosleep(0, 200000000); } $Conf->update_schema_version(null); error_log($Opt["dbName"] . ": updating schema from version " . $Conf->sversion); if ($Conf->sversion == 6 && Dbl::ql("alter table ReviewRequest add `reason` text")) { $Conf->update_schema_version(7); } if ($Conf->sversion == 7 && Dbl::ql("alter table PaperReview add `textField7` mediumtext NOT NULL") && Dbl::ql("alter table PaperReview add `textField8` mediumtext NOT NULL") && Dbl::ql("insert into ReviewFormField set fieldName='textField7', shortName='Additional text field'") && Dbl::ql("insert into ReviewFormField set fieldName='textField8', shortName='Additional text field'")) { $Conf->update_schema_version(8); } if ($Conf->sversion == 8 && Dbl::ql("alter table ReviewFormField add `levelChar` tinyint(1) NOT NULL default '0'") && Dbl::ql("alter table PaperReviewArchive add `textField7` mediumtext NOT NULL") && Dbl::ql("alter table PaperReviewArchive add `textField8` mediumtext NOT NULL")) { $Conf->update_schema_version(9); } if ($Conf->sversion == 9 && Dbl::ql("alter table Paper add `sha1` varbinary(20) NOT NULL default ''")) { $Conf->update_schema_version(10); } if ($Conf->sversion == 10 && Dbl::ql("alter table PaperReview add `reviewRound` tinyint(1) NOT NULL default '0'") && Dbl::ql("alter table PaperReviewArchive add `reviewRound` tinyint(1) NOT NULL default '0'") && Dbl::ql("alter table PaperReview add key `reviewRound` (`reviewRound`)") && $Conf->update_schema_version(11)) { if (count($Conf->round_list()) > 1) { // update review rounds (XXX locking) $result = Dbl::ql("select paperId, tag from PaperTag where tag like '%~%'"); $rrs = array(); while ($row = edb_row($result)) { list($contact, $round) = explode("~", $row[1]); if ($round = array_search($round, $Conf->round_list())) { if (!isset($rrs[$round])) { $rrs[$round] = array(); } $rrs[$round][] = "(contactId={$contact} and paperId={$row['0']})"; } } foreach ($rrs as $round => $pairs) { $q = "update PaperReview set reviewRound={$round} where " . join(" or ", $pairs); Dbl::ql($q); } $x = trim(preg_replace('/(\\S+)\\s*/', "tag like '%~\$1' or ", $Conf->setting_data("tag_rounds"))); Dbl::ql("delete from PaperTag where " . substr($x, 0, strlen($x) - 3)); } } if ($Conf->sversion == 11 && Dbl::ql("create table `ReviewRating` (\n `reviewId` int(11) NOT NULL,\n `contactId` int(11) NOT NULL,\n `rating` tinyint(1) NOT NULL default '0',\n UNIQUE KEY `reviewContact` (`reviewId`,`contactId`),\n UNIQUE KEY `reviewContactRating` (`reviewId`,`contactId`,`rating`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8")) { $Conf->update_schema_version(12); } if ($Conf->sversion == 12 && Dbl::ql("alter table PaperReview add `reviewToken` int(11) NOT NULL default '0'")) { $Conf->update_schema_version(13); } if ($Conf->sversion == 13 && Dbl::ql("alter table OptionType add `optionValues` text NOT NULL default ''")) { $Conf->update_schema_version(14); } if ($Conf->sversion == 14 && Dbl::ql("insert into Settings (name, value) select 'rev_tokens', count(reviewId) from PaperReview where reviewToken!=0 on duplicate key update value=values(value)")) { $Conf->update_schema_version(15); } if ($Conf->sversion == 15) { // It's OK if this fails! Update 11 added reviewRound to // PaperReviewArchive (so old databases have the column), but I forgot // to upgrade schema.sql (so new databases lack the column). Dbl::ql("alter table PaperReviewArchive add `reviewRound` tinyint(1) NOT NULL default '0'"); $OK = true; $Conf->update_schema_version(16); } if ($Conf->sversion == 16 && Dbl::ql("alter table PaperReview add `reviewEditVersion` int(1) NOT NULL default '0'")) { $Conf->update_schema_version(17); } if ($Conf->sversion == 17 && Dbl::ql("alter table PaperReviewPreference add key `paperId` (`paperId`)") && Dbl::ql("create table PaperRank (\n `paperId` int(11) NOT NULL,\n `contactId` int(11) NOT NULL,\n `rank` int(11) NOT NULL,\n UNIQUE KEY `contactPaper` (`contactId`,`paperId`),\n KEY `paperId` (`paperId`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8;")) { $Conf->update_schema_version(18); } if ($Conf->sversion == 18 && Dbl::ql("alter table PaperComment add `replyTo` int(11) NOT NULL")) { $Conf->update_schema_version(19); } if ($Conf->sversion == 19 && Dbl::ql("drop table PaperRank")) { $Conf->update_schema_version(20); } if ($Conf->sversion == 20 && Dbl::ql("alter table PaperComment add `timeNotified` int(11) NOT NULL default '0'")) { $Conf->update_schema_version(21); } if ($Conf->sversion == 21 && Dbl::ql("update PaperConflict set conflictType=8 where conflictType=3")) { $Conf->update_schema_version(22); } if ($Conf->sversion == 22 && Dbl::ql("insert into ChairAssistant (contactId) select contactId from Chair on duplicate key update ChairAssistant.contactId=ChairAssistant.contactId") && Dbl::ql("update ContactInfo set roles=roles+2 where roles=5")) { $Conf->update_schema_version(23); } if ($Conf->sversion == 23) { $Conf->update_schema_version(24); } if ($Conf->sversion == 24 && Dbl::ql("alter table ContactInfo add `preferredEmail` varchar(120)")) { $Conf->update_schema_version(25); } if ($Conf->sversion == 25) { if ($Conf->settings["final_done"] > 0 && !isset($Conf->settings["final_soft"]) && Dbl::ql("insert into Settings (name, value) values ('final_soft', " . $Conf->settings["final_done"] . ") on duplicate key update value=values(value)")) { $Conf->settings["final_soft"] = $Conf->settings["final_done"]; } $Conf->update_schema_version(26); } if ($Conf->sversion == 26 && Dbl::ql("alter table PaperOption add `data` text") && Dbl::ql("alter table OptionType add `type` tinyint(1) NOT NULL default '0'") && Dbl::ql("update OptionType set type=2 where optionValues='i'") && Dbl::ql("update OptionType set type=1 where type=0 and optionValues!=''")) { $Conf->update_schema_version(27); } if ($Conf->sversion == 27 && Dbl::ql("alter table PaperStorage add `sha1` varbinary(20) NOT NULL default ''") && Dbl::ql("alter table PaperStorage add `documentType` int(3) NOT NULL default '0'") && Dbl::ql("update PaperStorage s, Paper p set s.sha1=p.sha1 where s.paperStorageId=p.paperStorageId and p.finalPaperStorageId=0 and s.paperStorageId>0") && Dbl::ql("update PaperStorage s, Paper p set s.sha1=p.sha1, s.documentType=" . DTYPE_FINAL . " where s.paperStorageId=p.finalPaperStorageId and s.paperStorageId>0")) { $Conf->update_schema_version(28); } if ($Conf->sversion == 28 && Dbl::ql("alter table OptionType add `sortOrder` tinyint(1) NOT NULL default '0'")) { $Conf->update_schema_version(29); } if ($Conf->sversion == 29 && Dbl::ql("delete from Settings where name='pldisplay_default'")) { $Conf->update_schema_version(30); } if ($Conf->sversion == 30 && Dbl::ql("DROP TABLE IF EXISTS `Formula`") && Dbl::ql("CREATE TABLE `Formula` (\n `formulaId` int(11) NOT NULL auto_increment,\n `name` varchar(200) NOT NULL,\n `heading` varchar(200) NOT NULL default '',\n `headingTitle` text NOT NULL default '',\n `expression` text NOT NULL,\n `authorView` tinyint(1) NOT NULL default '1',\n PRIMARY KEY (`formulaId`),\n UNIQUE KEY `formulaId` (`formulaId`),\n UNIQUE KEY `name` (`name`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8")) { $Conf->update_schema_version(31); } if ($Conf->sversion == 31 && Dbl::ql("alter table Formula add `createdBy` int(11) NOT NULL default '0'") && Dbl::ql("alter table Formula add `timeModified` int(11) NOT NULL default '0'") && Dbl::ql("alter table Formula drop index `name`")) { $Conf->update_schema_version(32); } if ($Conf->sversion == 32 && Dbl::ql("alter table PaperComment add key `timeModified` (`timeModified`)")) { $Conf->update_schema_version(33); } if ($Conf->sversion == 33 && Dbl::ql("alter table PaperComment add `paperStorageId` int(11) NOT NULL default '0'")) { $Conf->update_schema_version(34); } if ($Conf->sversion == 34 && Dbl::ql("alter table ContactInfo add `contactTags` text")) { $Conf->update_schema_version(35); } if ($Conf->sversion == 35 && Dbl::ql("alter table ContactInfo modify `defaultWatch` int(11) NOT NULL default '2'") && Dbl::ql("alter table PaperWatch modify `watch` int(11) NOT NULL default '0'")) { $Conf->update_schema_version(36); } if ($Conf->sversion == 36 && Dbl::ql("alter table PaperReview add `reviewNotified` int(1) default NULL") && Dbl::ql("alter table PaperReviewArchive add `reviewNotified` int(1) default NULL")) { $Conf->update_schema_version(37); } if ($Conf->sversion == 37 && Dbl::ql("alter table OptionType add `displayType` tinyint(1) NOT NULL default '0'")) { $Conf->update_schema_version(38); } if ($Conf->sversion == 38 && Dbl::ql("update PaperComment set forReviewers=1 where forReviewers=-1")) { $Conf->update_schema_version(39); } if ($Conf->sversion == 39 && Dbl::ql("CREATE TABLE `MailLog` (\n `mailId` int(11) NOT NULL auto_increment,\n `recipients` varchar(200) NOT NULL,\n `paperIds` text,\n `cc` text,\n `replyto` text,\n `subject` text,\n `emailBody` text,\n PRIMARY KEY (`mailId`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8")) { $Conf->update_schema_version(40); } if ($Conf->sversion == 40 && Dbl::ql("alter table Paper add `capVersion` int(1) NOT NULL default '0'")) { $Conf->update_schema_version(41); } if ($Conf->sversion == 41 && Dbl::ql("alter table Paper modify `mimetype` varchar(80) NOT NULL default ''") && Dbl::ql("alter table PaperStorage modify `mimetype` varchar(80) NOT NULL default ''")) { $Conf->update_schema_version(42); } if ($Conf->sversion == 42 && Dbl::ql("alter table PaperComment add `ordinal` int(11) NOT NULL default '0'")) { $Conf->update_schema_version(43); } if ($Conf->sversion == 42 && ($result = Dbl::ql("describe PaperComment `ordinal`")) && ($o = edb_orow($result)) && substr($o->Type, 0, 3) == "int" && (!$o->Null || $o->Null == "NO") && (!$o->Default || $o->Default == "0")) { $Conf->update_schema_version(43); } if ($Conf->sversion == 43 && Dbl::ql("alter table Paper add `withdrawReason` text")) { $Conf->update_schema_version(44); } if ($Conf->sversion == 44 && Dbl::ql("alter table PaperStorage add `filename` varchar(255)")) { $Conf->update_schema_version(45); } if ($Conf->sversion == 45 && Dbl::ql("alter table PaperReview add `timeRequested` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReview add `timeRequestNotified` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReviewArchive add `timeRequested` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReviewArchive add `timeRequestNotified` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReview drop column `requestedOn`") && Dbl::ql("alter table PaperReviewArchive drop column `requestedOn`")) { $Conf->update_schema_version(46); } if ($Conf->sversion == 46 && Dbl::ql("alter table ContactInfo add `disabled` tinyint(1) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(47); } if ($Conf->sversion == 47 && Dbl::ql("delete from ti using TopicInterest ti left join TopicArea ta using (topicId) where ta.topicId is null")) { $Conf->update_schema_version(48); } if ($Conf->sversion == 48 && Dbl::ql("alter table PaperReview add `reviewAuthorNotified` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReviewArchive add `reviewAuthorNotified` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReviewArchive add `reviewToken` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(49); } if ($Conf->sversion == 49 && Dbl::ql("alter table PaperOption drop index `paperOption`") && Dbl::ql("alter table PaperOption add index `paperOption` (`paperId`,`optionId`,`value`)")) { $Conf->update_schema_version(50); } if ($Conf->sversion == 50 && Dbl::ql("alter table Paper add `managerContactId` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(51); } if ($Conf->sversion == 51 && Dbl::ql("alter table Paper drop column `numComments`") && Dbl::ql("alter table Paper drop column `numAuthorComments`")) { $Conf->update_schema_version(52); } // Due to a bug in the schema updater, some databases might have // sversion>=53 but no `PaperComment.commentType` column. Fix them. if (($Conf->sversion == 52 || $Conf->sversion >= 53 && ($result = Dbl::ql("show columns from PaperComment like 'commentType'")) && edb_nrows($result) == 0) && Dbl::ql("lock tables PaperComment write, Settings write") && Dbl::ql("alter table PaperComment add `commentType` int(11) NOT NULL DEFAULT '0'")) { $new_sversion = max($Conf->sversion, 53); $result = Dbl::ql("show columns from PaperComment like 'forAuthors'"); if (!$result || edb_nrows($result) == 0 || Dbl::ql("update PaperComment set commentType=" . (COMMENTTYPE_AUTHOR | COMMENTTYPE_RESPONSE) . " where forAuthors=2") && Dbl::ql("update PaperComment set commentType=commentType|" . COMMENTTYPE_DRAFT . " where forAuthors=2 and forReviewers=0") && Dbl::ql("update PaperComment set commentType=" . COMMENTTYPE_ADMINONLY . " where forAuthors=0 and forReviewers=2") && Dbl::ql("update PaperComment set commentType=" . COMMENTTYPE_PCONLY . " where forAuthors=0 and forReviewers=0") && Dbl::ql("update PaperComment set commentType=" . COMMENTTYPE_REVIEWER . " where forAuthors=0 and forReviewers=1") && Dbl::ql("update PaperComment set commentType=" . COMMENTTYPE_AUTHOR . " where forAuthors!=0 and forAuthors!=2") && Dbl::ql("update PaperComment set commentType=commentType|" . COMMENTTYPE_BLIND . " where blind=1")) { $Conf->update_schema_version($new_sversion); } } if ($Conf->sversion < 53) { Dbl::qx_raw($Conf->dblink, "alter table PaperComment drop column `commentType`"); } Dbl::ql("unlock tables"); if ($Conf->sversion == 53 && Dbl::ql("alter table PaperComment drop column `forReviewers`") && Dbl::ql("alter table PaperComment drop column `forAuthors`") && Dbl::ql("alter table PaperComment drop column `blind`")) { $Conf->update_schema_version(54); } if ($Conf->sversion == 54 && Dbl::ql("alter table PaperStorage add `infoJson` varchar(255) DEFAULT NULL")) { $Conf->update_schema_version(55); } if ($Conf->sversion == 55 && Dbl::ql("alter table ContactInfo modify `password` varbinary(2048) NOT NULL")) { $Conf->update_schema_version(56); } if ($Conf->sversion == 56 && Dbl::ql("alter table Settings modify `data` blob")) { $Conf->update_schema_version(57); } if ($Conf->sversion == 57 && Dbl::ql("DROP TABLE IF EXISTS `Capability`") && Dbl::ql("CREATE TABLE `Capability` (\n `capabilityId` int(11) NOT NULL AUTO_INCREMENT,\n `capabilityType` int(11) NOT NULL,\n `contactId` int(11) NOT NULL,\n `paperId` int(11) NOT NULL,\n `timeExpires` int(11) NOT NULL,\n `salt` varbinary(255) NOT NULL,\n `data` blob,\n PRIMARY KEY (`capabilityId`),\n UNIQUE KEY `capabilityId` (`capabilityId`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8") && Dbl::ql("DROP TABLE IF EXISTS `CapabilityMap`") && Dbl::ql("CREATE TABLE `CapabilityMap` (\n `capabilityValue` varbinary(255) NOT NULL,\n `capabilityId` int(11) NOT NULL,\n `timeExpires` int(11) NOT NULL,\n PRIMARY KEY (`capabilityValue`),\n UNIQUE KEY `capabilityValue` (`capabilityValue`)\n) ENGINE=MyISAM DEFAULT CHARSET=utf8")) { $Conf->update_schema_version(58); } if ($Conf->sversion == 58 && Dbl::ql("alter table PaperReview modify `paperSummary` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `commentsToAuthor` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `commentsToPC` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `commentsToAddress` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `weaknessOfPaper` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `strengthOfPaper` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `textField7` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReview modify `textField8` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `paperSummary` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `commentsToAuthor` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `commentsToPC` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `commentsToAddress` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `weaknessOfPaper` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `strengthOfPaper` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `textField7` mediumtext DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive modify `textField8` mediumtext DEFAULT NULL")) { $Conf->update_schema_version(59); } if ($Conf->sversion == 59 && Dbl::ql("alter table ActionLog modify `action` varbinary(4096) NOT NULL") && Dbl::ql("alter table ContactInfo modify `note` varbinary(4096) DEFAULT NULL") && Dbl::ql("alter table ContactInfo modify `collaborators` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table ContactInfo modify `contactTags` varbinary(4096) DEFAULT NULL") && Dbl::ql("alter table Formula modify `headingTitle` varbinary(4096) NOT NULL") && Dbl::ql("alter table Formula modify `expression` varbinary(4096) NOT NULL") && Dbl::ql("alter table OptionType modify `description` varbinary(8192) DEFAULT NULL") && Dbl::ql("alter table OptionType modify `optionValues` varbinary(8192) NOT NULL") && Dbl::ql("alter table PaperReviewRefused modify `reason` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table ReviewFormField modify `description` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table ReviewFormOptions modify `description` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table ReviewRequest modify `reason` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table Settings modify `data` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table ContactAddress modify `addressLine1` varchar(2048) NOT NULL") && Dbl::ql("alter table ContactAddress modify `addressLine2` varchar(2048) NOT NULL") && Dbl::ql("alter table ContactAddress modify `city` varchar(2048) NOT NULL") && Dbl::ql("alter table ContactAddress modify `state` varchar(2048) NOT NULL") && Dbl::ql("alter table ContactAddress modify `zipCode` varchar(2048) NOT NULL") && Dbl::ql("alter table ContactAddress modify `country` varchar(2048) NOT NULL") && Dbl::ql("alter table PaperTopic modify `topicId` int(11) NOT NULL") && Dbl::ql("alter table PaperTopic modify `paperId` int(11) NOT NULL") && Dbl::ql("drop table if exists ChairTag")) { $Conf->update_schema_version(60); } if ($Conf->sversion == 60 && Dbl::ql("insert into Settings (name,value,data) select concat('msg.',substr(name,1,length(name)-3)), value, data from Settings where name='homemsg' or name='conflictdefmsg'") && $Conf->update_schema_version(61)) { foreach (array("conflictdef", "home") as $k) { if (isset($Conf->settingTexts["{$k}msg"])) { $Conf->settingTexts["msg.{$k}"] = $Conf->settingTexts["{$k}msg"]; } } $Conf->settings["allowPaperOption"] = 61; } if ($Conf->sversion == 61 && Dbl::ql("alter table Capability modify `data` varbinary(4096) DEFAULT NULL")) { $Conf->update_schema_version(62); } if (!isset($Conf->settings["outcome_map"])) { $ojson = array(); $result = Dbl::ql("select * from ReviewFormOptions where fieldName='outcome'"); while ($row = edb_orow($result)) { $ojson[$row->level] = $row->description; } $Conf->save_setting("outcome_map", 1, $ojson); } if ($Conf->sversion == 62 && isset($Conf->settings["outcome_map"])) { $Conf->update_schema_version(63); } if (!isset($Conf->settings["review_form"]) && $Conf->sversion < 65) { update_schema_create_review_form($Conf); } if ($Conf->sversion == 63 && isset($Conf->settings["review_form"])) { $Conf->update_schema_version(64); } if ($Conf->sversion == 64 && Dbl::ql("drop table if exists `ReviewFormField`") && Dbl::ql("drop table if exists `ReviewFormOptions`")) { $Conf->update_schema_version(65); } if (!isset($Conf->settings["options"]) && $Conf->sversion < 67) { update_schema_create_options($Conf); } if ($Conf->sversion == 65 && isset($Conf->settings["options"])) { $Conf->update_schema_version(66); } if ($Conf->sversion == 66 && Dbl::ql("drop table if exists `OptionType`")) { $Conf->update_schema_version(67); } if ($Conf->sversion == 67 && Dbl::ql("alter table PaperComment modify `comment` varbinary(32767) DEFAULT NULL") && Dbl::ql("alter table PaperComment add `commentTags` varbinary(1024) DEFAULT NULL")) { $Conf->update_schema_version(68); } if ($Conf->sversion == 68 && Dbl::ql("alter table PaperReviewPreference add `expertise` int(4) DEFAULT NULL")) { $Conf->update_schema_version(69); } if ($Conf->sversion == 69 && Dbl::ql("alter table Paper drop column `pcPaper`")) { $Conf->update_schema_version(70); } if ($Conf->sversion == 70 && Dbl::ql("alter table ContactInfo modify `voicePhoneNumber` varbinary(256) DEFAULT NULL") && Dbl::ql("alter table ContactInfo modify `faxPhoneNumber` varbinary(256) DEFAULT NULL") && Dbl::ql("alter table ContactInfo modify `collaborators` varbinary(8192) DEFAULT NULL") && Dbl::ql("alter table ContactInfo drop column `note`") && Dbl::ql("alter table ContactInfo add `data` varbinary(32767) DEFAULT NULL")) { $Conf->update_schema_version(71); } if ($Conf->sversion == 71 && Dbl::ql("alter table Settings modify `name` varbinary(256) DEFAULT NULL") && Dbl::ql("update Settings set name=rtrim(name)")) { $Conf->update_schema_version(72); } if ($Conf->sversion == 72 && Dbl::ql("update TopicInterest set interest=-2 where interest=0") && Dbl::ql("update TopicInterest set interest=4 where interest=2") && Dbl::ql("delete from TopicInterest where interest=1")) { $Conf->update_schema_version(73); } if ($Conf->sversion == 73 && Dbl::ql("alter table PaperStorage add `size` bigint(11) DEFAULT NULL") && Dbl::ql("update PaperStorage set `size`=length(paper) where paper is not null")) { $Conf->update_schema_version(74); } if ($Conf->sversion == 74 && Dbl::ql("alter table ContactInfo drop column `visits`")) { $Conf->update_schema_version(75); } if ($Conf->sversion == 75) { foreach (array("capability_gc", "s3_scope", "s3_signing_key") as $k) { if (isset($Conf->settings[$k])) { $Conf->save_setting("__" . $k, $Conf->settings[$k], get($Conf->settingTexts, $k)); $Conf->save_setting($k, null); } } $Conf->update_schema_version(76); } if ($Conf->sversion == 76 && Dbl::ql("update PaperReviewPreference set expertise=-expertise")) { $Conf->update_schema_version(77); } if ($Conf->sversion == 77 && Dbl::ql("alter table MailLog add `q` varchar(4096)")) { $Conf->update_schema_version(78); } if ($Conf->sversion == 78 && Dbl::ql("alter table MailLog add `t` varchar(200)")) { $Conf->update_schema_version(79); } if ($Conf->sversion == 79 && Dbl::ql("alter table ContactInfo add `passwordTime` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(80); } if ($Conf->sversion == 80 && Dbl::ql("alter table PaperReview modify `reviewRound` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperReviewArchive modify `reviewRound` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(81); } if ($Conf->sversion == 81 && Dbl::ql("alter table PaperStorage add `filterType` int(3) DEFAULT NULL") && Dbl::ql("alter table PaperStorage add `originalStorageId` int(11) DEFAULT NULL")) { $Conf->update_schema_version(82); } if ($Conf->sversion == 82 && Dbl::ql("update Settings set name='msg.resp_instrux' where name='msg.responseinstructions'")) { $Conf->update_schema_version(83); } if ($Conf->sversion == 83 && Dbl::ql("alter table PaperComment add `commentRound` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(84); } if ($Conf->sversion == 84 && Dbl::ql("insert ignore into Settings (name, value) select 'resp_active', value from Settings where name='resp_open'")) { $Conf->update_schema_version(85); } if ($Conf->sversion == 85 && Dbl::ql("DROP TABLE IF EXISTS `PCMember`") && Dbl::ql("DROP TABLE IF EXISTS `ChairAssistant`") && Dbl::ql("DROP TABLE IF EXISTS `Chair`")) { $Conf->update_schema_version(86); } if ($Conf->sversion == 86 && update_schema_transfer_address($Conf)) { $Conf->update_schema_version(87); } if ($Conf->sversion == 87 && Dbl::ql("DROP TABLE IF EXISTS `ContactAddress`")) { $Conf->update_schema_version(88); } if ($Conf->sversion == 88 && Dbl::ql("alter table ContactInfo drop key `name`") && Dbl::ql("alter table ContactInfo drop key `affiliation`") && Dbl::ql("alter table ContactInfo drop key `email_3`") && Dbl::ql("alter table ContactInfo drop key `firstName_2`") && Dbl::ql("alter table ContactInfo drop key `lastName`")) { $Conf->update_schema_version(89); } if ($Conf->sversion == 89 && update_schema_unaccented_name($Conf)) { $Conf->update_schema_version(90); } if ($Conf->sversion == 90 && Dbl::ql("alter table PaperReview add `reviewAuthorSeen` int(11) DEFAULT NULL")) { $Conf->update_schema_version(91); } if ($Conf->sversion == 91 && Dbl::ql("alter table PaperReviewArchive add `reviewAuthorSeen` int(11) DEFAULT NULL")) { $Conf->update_schema_version(92); } if ($Conf->sversion == 92 && Dbl::ql("alter table Paper drop key `titleAbstractText`") && Dbl::ql("alter table Paper drop key `allText`") && Dbl::ql("alter table Paper drop key `authorText`") && Dbl::ql("alter table Paper modify `authorInformation` varbinary(8192) DEFAULT NULL") && Dbl::ql("alter table Paper modify `abstract` varbinary(16384) DEFAULT NULL") && Dbl::ql("alter table Paper modify `collaborators` varbinary(8192) DEFAULT NULL") && Dbl::ql("alter table Paper modify `withdrawReason` varbinary(1024) DEFAULT NULL")) { $Conf->update_schema_version(93); } if ($Conf->sversion == 93 && Dbl::ql("alter table TopicArea modify `topicName` varchar(200) DEFAULT NULL")) { $Conf->update_schema_version(94); } if ($Conf->sversion == 94 && Dbl::ql("alter table PaperOption modify `data` varbinary(32768) DEFAULT NULL")) { foreach (PaperOption::nonfixed_option_list($Conf) as $xopt) { if ($xopt->type === "text") { Dbl::ql("delete from PaperOption where optionId={$xopt->id} and data=''"); } } $Conf->update_schema_version(95); } if ($Conf->sversion == 95 && Dbl::ql("alter table Capability add unique key `salt` (`salt`)") && Dbl::ql("update Capability join CapabilityMap using (capabilityId) set Capability.salt=CapabilityMap.capabilityValue") && Dbl::ql("drop table if exists `CapabilityMap`")) { $Conf->update_schema_version(96); } if ($Conf->sversion == 96 && Dbl::ql("alter table ContactInfo add `passwordIsCdb` tinyint(1) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(97); } if ($Conf->sversion == 97 && Dbl::ql("alter table PaperReview add `reviewWordCount` int(11) DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive add `reviewWordCount` int(11) DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive drop key `reviewId`") && Dbl::ql("alter table PaperReviewArchive drop key `contactPaper`") && Dbl::ql("alter table PaperReviewArchive drop key `reviewSubmitted`") && Dbl::ql("alter table PaperReviewArchive drop key `reviewNeedsSubmit`") && Dbl::ql("alter table PaperReviewArchive drop key `reviewType`") && Dbl::ql("alter table PaperReviewArchive drop key `requestedBy`")) { $Conf->update_schema_version(98); } if ($Conf->sversion == 98) { update_schema_review_word_counts($Conf); $Conf->update_schema_version(99); } if ($Conf->sversion == 99 && Dbl::ql("alter table ContactInfo ENGINE=InnoDB") && Dbl::ql("alter table Paper ENGINE=InnoDB") && Dbl::ql("alter table PaperComment ENGINE=InnoDB") && Dbl::ql("alter table PaperConflict ENGINE=InnoDB") && Dbl::ql("alter table PaperOption ENGINE=InnoDB") && Dbl::ql("alter table PaperReview ENGINE=InnoDB") && Dbl::ql("alter table PaperStorage ENGINE=InnoDB") && Dbl::ql("alter table PaperTag ENGINE=InnoDB") && Dbl::ql("alter table PaperTopic ENGINE=InnoDB") && Dbl::ql("alter table Settings ENGINE=InnoDB")) { $Conf->update_schema_version(100); } if ($Conf->sversion == 100 && Dbl::ql("alter table ActionLog ENGINE=InnoDB") && Dbl::ql("alter table Capability ENGINE=InnoDB") && Dbl::ql("alter table Formula ENGINE=InnoDB") && Dbl::ql("alter table MailLog ENGINE=InnoDB") && Dbl::ql("alter table PaperReviewArchive ENGINE=InnoDB") && Dbl::ql("alter table PaperReviewPreference ENGINE=InnoDB") && Dbl::ql("alter table PaperReviewRefused ENGINE=InnoDB") && Dbl::ql("alter table PaperWatch ENGINE=InnoDB") && Dbl::ql("alter table ReviewRating ENGINE=InnoDB") && Dbl::ql("alter table ReviewRequest ENGINE=InnoDB") && Dbl::ql("alter table TopicArea ENGINE=InnoDB") && Dbl::ql("alter table TopicInterest ENGINE=InnoDB")) { $Conf->update_schema_version(101); } if ($Conf->sversion == 101 && Dbl::ql("alter table ActionLog modify `ipaddr` varbinary(32) DEFAULT NULL") && Dbl::ql("alter table MailLog modify `recipients` varbinary(200) NOT NULL") && Dbl::ql("alter table MailLog modify `q` varbinary(4096) DEFAULT NULL") && Dbl::ql("alter table MailLog modify `t` varbinary(200) DEFAULT NULL") && Dbl::ql("alter table Paper modify `mimetype` varbinary(80) NOT NULL DEFAULT ''") && Dbl::ql("alter table PaperStorage modify `mimetype` varbinary(80) NOT NULL DEFAULT ''") && Dbl::ql("alter table PaperStorage modify `filename` varbinary(255) DEFAULT NULL") && Dbl::ql("alter table PaperStorage modify `infoJson` varbinary(8192) DEFAULT NULL")) { $Conf->update_schema_version(102); } if ($Conf->sversion == 102 && Dbl::ql("alter table PaperReview modify `paperSummary` mediumblob") && Dbl::ql("alter table PaperReview modify `commentsToAuthor` mediumblob") && Dbl::ql("alter table PaperReview modify `commentsToPC` mediumblob") && Dbl::ql("alter table PaperReview modify `commentsToAddress` mediumblob") && Dbl::ql("alter table PaperReview modify `weaknessOfPaper` mediumblob") && Dbl::ql("alter table PaperReview modify `strengthOfPaper` mediumblob") && Dbl::ql("alter table PaperReview modify `textField7` mediumblob") && Dbl::ql("alter table PaperReview modify `textField8` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `paperSummary` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `commentsToAuthor` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `commentsToPC` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `commentsToAddress` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `weaknessOfPaper` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `strengthOfPaper` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `textField7` mediumblob") && Dbl::ql("alter table PaperReviewArchive modify `textField8` mediumblob")) { $Conf->update_schema_version(103); } if ($Conf->sversion == 103 && Dbl::ql("alter table Paper modify `title` varbinary(256) DEFAULT NULL") && Dbl::ql("alter table Paper drop key `title`")) { $Conf->update_schema_version(104); } if ($Conf->sversion == 104 && Dbl::ql("alter table PaperReview add `reviewFormat` tinyint(1) DEFAULT NULL") && Dbl::ql("alter table PaperReviewArchive add `reviewFormat` tinyint(1) DEFAULT NULL")) { $Conf->update_schema_version(105); } if ($Conf->sversion == 105 && Dbl::ql("alter table PaperComment add `commentFormat` tinyint(1) DEFAULT NULL")) { $Conf->update_schema_version(106); } if ($Conf->sversion == 106 && Dbl::ql("alter table PaperComment add `authorOrdinal` int(11) NOT NULL default '0'") && Dbl::ql("update PaperComment set authorOrdinal=ordinal where commentType>=" . COMMENTTYPE_AUTHOR)) { $Conf->update_schema_version(107); } // repair missing comment ordinals; reset incorrect `ordinal`s for // author-visible comments if ($Conf->sversion == 107) { $result = Dbl::ql("select paperId, commentId from PaperComment where ordinal=0 and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_PCONLY . " and commentType<" . COMMENTTYPE_AUTHOR . " order by commentId"); while ($row = edb_row($result)) { Dbl::ql("update PaperComment,\n(select coalesce(count(commentId),0) commentCount from Paper\n left join PaperComment on (PaperComment.paperId=Paper.paperId and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_PCONLY . " and commentType<" . COMMENTTYPE_AUTHOR . " and commentId<{$row['1']})\n where Paper.paperId={$row['0']} group by Paper.paperId) t\nset ordinal=(t.commentCount+1) where commentId={$row['1']}"); } $result = Dbl::ql("select paperId, commentId from PaperComment where ordinal=0 and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_AUTHOR . " order by commentId"); while ($row = edb_row($result)) { Dbl::ql("update PaperComment,\n(select coalesce(count(commentId),0) commentCount from Paper\n left join PaperComment on (PaperComment.paperId=Paper.paperId and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_AUTHOR . " and commentId<{$row['1']})\n where Paper.paperId={$row['0']} group by Paper.paperId) t\nset authorOrdinal=(t.commentCount+1) where commentId={$row['1']}"); } $result = Dbl::ql("select paperId, commentId from PaperComment where ordinal=authorOrdinal and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_AUTHOR . " order by commentId"); while ($row = edb_row($result)) { Dbl::ql("update PaperComment,\n(select coalesce(max(ordinal),0) maxOrdinal from Paper\n left join PaperComment on (PaperComment.paperId=Paper.paperId and (commentType&" . (COMMENTTYPE_RESPONSE | COMMENTTYPE_DRAFT) . ")=0 and commentType>=" . COMMENTTYPE_PCONLY . " and commentType<" . COMMENTTYPE_AUTHOR . " and commentId<{$row['1']})\n where Paper.paperId={$row['0']} group by Paper.paperId) t\nset ordinal=(t.maxOrdinal+1) where commentId={$row['1']}"); } $Conf->update_schema_version(108); } // contact tags format change if ($Conf->sversion == 108 && Dbl::ql("update ContactInfo set contactTags=substr(replace(contactTags, ' ', '#0 ') from 3)") && Dbl::ql("update ContactInfo set contactTags=replace(contactTags, '#0#0 ', '#0 ')")) { $Conf->update_schema_version(109); } if ($Conf->sversion == 109 && Dbl::ql("alter table PaperTag modify `tagIndex` float NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(110); } if ($Conf->sversion == 110 && Dbl::ql("alter table ContactInfo drop `faxPhoneNumber`") && Dbl::ql("alter table ContactInfo add `country` varbinary(256) default null") && update_schema_transfer_country($Conf)) { $Conf->update_schema_version(111); } if ($Conf->sversion == 111) { update_schema_review_word_counts($Conf); $Conf->update_schema_version(112); } if ($Conf->sversion == 112 && Dbl::ql("alter table ContactInfo add `passwordUseTime` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table ContactInfo add `updateTime` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("update ContactInfo set passwordUseTime=lastLogin where passwordUseTime=0")) { $Conf->update_schema_version(113); } if ($Conf->sversion == 113 && Dbl::ql("drop table if exists `PaperReviewArchive`")) { $Conf->update_schema_version(114); } if ($Conf->sversion == 114 && Dbl::ql("alter table PaperReview add `timeDisplayed` int(11) NOT NULL DEFAULT '0'") && Dbl::ql("alter table PaperComment add `timeDisplayed` int(11) NOT NULL DEFAULT '0'")) { $Conf->update_schema_version(115); } if ($Conf->sversion == 115 && Dbl::ql("alter table Formula drop column `authorView`")) { $Conf->update_schema_version(116); } if ($Conf->sversion == 116 && Dbl::ql("alter table PaperComment add `commentOverflow` longblob DEFAULT NULL")) { $Conf->update_schema_version(117); } if ($Conf->sversion == 117 && update_schema_drop_keys_if_exist("PaperTopic", ["paperTopic", "PRIMARY"]) && Dbl::ql("alter table PaperTopic add primary key (`paperId`,`topicId`)") && update_schema_drop_keys_if_exist("TopicInterest", ["contactTopic", "PRIMARY"]) && Dbl::ql("alter table TopicInterest add primary key (`contactId`,`topicId`)")) { $Conf->update_schema_version(118); } if ($Conf->sversion == 118 && update_schema_drop_keys_if_exist("PaperTag", ["paperTag", "PRIMARY"]) && Dbl::ql("alter table PaperTag add primary key (`paperId`,`tag`)") && update_schema_drop_keys_if_exist("PaperReviewPreference", ["paperId", "PRIMARY"]) && Dbl::ql("alter table PaperReviewPreference add primary key (`paperId`,`contactId`)") && update_schema_drop_keys_if_exist("PaperConflict", ["contactPaper", "contactPaperConflict", "PRIMARY"]) && Dbl::ql("alter table PaperConflict add primary key (`contactId`,`paperId`)") && Dbl::ql("alter table MailLog modify `paperIds` blob") && Dbl::ql("alter table MailLog modify `cc` blob") && Dbl::ql("alter table MailLog modify `replyto` blob") && Dbl::ql("alter table MailLog modify `subject` blob") && Dbl::ql("alter table MailLog modify `emailBody` blob")) { $Conf->update_schema_version(119); } if ($Conf->sversion == 119 && update_schema_drop_keys_if_exist("PaperWatch", ["contactPaper", "contactPaperWatch", "PRIMARY"]) && Dbl::ql("alter table PaperWatch add primary key (`paperId`,`contactId`)")) { $Conf->update_schema_version(120); } if ($Conf->sversion == 120 && Dbl::ql("alter table Paper add `paperFormat` tinyint(1) DEFAULT NULL")) { $Conf->update_schema_version(121); } if ($Conf->sversion == 121 && Dbl::ql_raw("update PaperReview r, Paper p set r.reviewNeedsSubmit=1 where p.paperId=r.paperId and p.timeSubmitted<=0 and r.reviewSubmitted is null") && Dbl::ql_raw("update PaperReview r, Paper p, PaperReview rq set r.reviewNeedsSubmit=0 where p.paperId=r.paperId and p.paperId=rq.paperId and p.timeSubmitted<=0 and r.reviewType=" . REVIEW_SECONDARY . " and r.contactId=rq.requestedBy and rq.reviewType<" . REVIEW_SECONDARY . " and rq.reviewSubmitted is not null") && Dbl::ql_raw("update PaperReview r, Paper p, PaperReview rq set r.reviewNeedsSubmit=-1 where p.paperId=r.paperId and p.paperId=rq.paperId and p.timeSubmitted<=0 and r.reviewType=" . REVIEW_SECONDARY . " and r.contactId=rq.requestedBy and rq.reviewType<" . REVIEW_SECONDARY . " and r.reviewNeedsSubmit=0")) { $Conf->update_schema_version(122); } if ($Conf->sversion == 122 && Dbl::ql("alter table ReviewRequest add `reviewRound` int(1) DEFAULT NULL")) { $Conf->update_schema_version(123); } if ($Conf->sversion == 123 && Dbl::ql("update ContactInfo set disabled=1 where password='' and email regexp '^anonymous[0-9]*\$'")) { $Conf->update_schema_version(124); } if ($Conf->sversion == 124 && Dbl::ql("update ContactInfo set password='' where password='******' or passwordIsCdb")) { $Conf->update_schema_version(125); } if ($Conf->sversion == 125 && Dbl::ql("alter table ContactInfo drop column `passwordIsCdb`")) { $Conf->update_schema_version(126); } if ($Conf->sversion == 126 && Dbl::ql("update ContactInfo set disabled=1, password='' where email regexp '^anonymous[0-9]*\$'")) { $Conf->update_schema_version(127); } if ($Conf->sversion == 127 && Dbl::ql("update PaperReview set reviewWordCount=null")) { $Conf->update_schema_version(128); } if ($Conf->sversion == 128 && update_schema_bad_comment_timeDisplayed($Conf)) { $Conf->update_schema_version(129); } if ($Conf->sversion == 129 && Dbl::ql("update PaperComment set timeDisplayed=1 where timeDisplayed=0 and timeNotified>0")) { $Conf->update_schema_version(130); } if ($Conf->sversion == 130 && Dbl::ql("DROP TABLE IF EXISTS `PaperTagAnno`") && Dbl::ql("CREATE TABLE `PaperTagAnno` (\n `tag` varchar(40) NOT NULL, # see TAG_MAXLEN in header.php\n `annoId` int(11) NOT NULL,\n `tagIndex` float NOT NULL DEFAULT '0',\n `heading` varbinary(8192) DEFAULT NULL,\n `annoFormat` tinyint(1) DEFAULT NULL,\n `infoJson` varbinary(32768) DEFAULT NULL,\n PRIMARY KEY (`tag`,`annoId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8")) { $Conf->update_schema_version(131); } if ($Conf->sversion == 131 && Dbl::ql("alter table PaperStorage modify `infoJson` varbinary(32768) DEFAULT NULL")) { $Conf->update_schema_version(132); } Dbl::ql("delete from Settings where name='__schema_lock'"); }
function update_schema_version($n) { if (!$n) { $n = Dbl::fetch_ivalue("select value from Settings where name='allowPaperOption'"); } if ($n && Dbl::ql("update Settings set value={$n} where name='allowPaperOption'")) { $this->sversion = $this->settings["allowPaperOption"] = $n; return true; } else { return false; } }
if ($qreq->fn === "events") { json_exit(["ok" => false]); } } if ($qreq->fn === "searchcompletion") { $s = new PaperSearch($Me, ""); $Conf->ajaxExit(array("ok" => true, "searchcompletion" => $s->search_completion())); } // from here on: `status` and `track` requests if ($qreq->fn === "track") { MeetingTracker::track_api($qreq, $Me); } // may fall through to act like `status` $j = $Me->my_deadlines($Conf->paper); if ($qreq->conflist && $Me->has_email() && ($cdb = Contact::contactdb())) { $j->conflist = array(); $result = Dbl::ql($cdb, "select c.confid, siteclass, shortName, url\n from Roles r join Conferences c on (c.confid=r.confid)\n join ContactInfo u on (u.contactDbId=r.contactDbId)\n where u.email=? order by r.updated_at desc", $Me->email); while ($row = edb_orow($result)) { $row->confid = (int) $row->confid; $j->conflist[] = $row; } } $pj = (object) array(); if ($Conf->paper && $Me->can_view_tags($Conf->paper)) { $Conf->paper->add_tag_info_json($pj, $Me); } if (count((array) $pj)) { $j->p = [$Conf->paper->paperId => $pj]; } $j->ok = true; $Conf->ajaxExit($j);
function load_settings() { global $Now; // load settings from database $this->settings = array(); $this->settingTexts = array(); foreach ($this->opt_override ?: [] as $k => $v) { if ($v === null) { unset($this->opt[$k]); } else { $this->opt[$k] = $v; } } $this->opt_override = []; $this->_pc_seeall_cache = null; $this->deadlineCache = null; $result = $this->q_raw("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); $this->opt_override[$okey] = get($this->opt, $okey); $this->opt[$okey] = $row[2] === null ? (int) $row[1] : $row[2]; } } Dbl::free($result); // update schema $this->sversion = $this->settings["allowPaperOption"]; if ($this->sversion < 108) { require_once "updateschema.php"; $old_nerrors = Dbl::$nerrors; updateSchema($this); Dbl::$nerrors = $old_nerrors; } // invalidate all caches after loading from backup if (isset($this->settings["frombackup"]) && $this->invalidate_caches()) { $this->qe_raw("delete from Settings where name='frombackup' and value=" . $this->settings["frombackup"]); unset($this->settings["frombackup"]); } else { $this->invalidate_caches(["rf" => true]); } // update options if (isset($this->opt["ldapLogin"]) && !$this->opt["ldapLogin"]) { unset($this->opt["ldapLogin"]); } if (isset($this->opt["httpAuthLogin"]) && !$this->opt["httpAuthLogin"]) { unset($this->opt["httpAuthLogin"]); } // set conferenceKey if (!isset($this->opt["conferenceKey"])) { if (!isset($this->settingTexts["conf_key"]) && ($key = hotcrp_random_bytes(32)) !== false) { $this->save_setting("conf_key", 1, $key); } $this->opt["conferenceKey"] = get($this->settingTexts, "conf_key", ""); } // set capability key if (!get($this->settings, "cap_key") && !get($this->opt, "disableCapabilities") && !(($key = hotcrp_random_bytes(16)) !== false && ($key = base64_encode($key)) && $this->save_setting("cap_key", 1, $key))) { $this->opt["disableCapabilities"] = true; } // GC old capabilities if (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}"); } } $this->q_raw("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(); }
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(); }
function render($sv) { global $Conf; $sv->echo_checkbox("rev_open", "<b>Open site for reviewing</b>"); $sv->echo_checkbox("cmt_always", "Allow comments even if reviewing is closed"); echo "<div class='g'></div>\n"; $sv->echo_checkbox('pcrev_any', "PC members can review <strong>any</strong> submitted paper"); echo "<div class='g'></div>\n"; echo "<strong>Review anonymity:</strong> Are reviewer names hidden from authors?<br />\n"; $sv->echo_radio_table("rev_blind", array(Conf::BLIND_ALWAYS => "Yes—reviews are anonymous", Conf::BLIND_NEVER => "No—reviewer names are visible to authors", Conf::BLIND_OPTIONAL => "Depends—reviewers decide whether to expose their names")); echo "<div class='g'></div>\n"; $sv->echo_checkbox('rev_notifychair', 'Notify PC chairs of newly submitted reviews by email'); // Deadlines echo "<h3 id=\"rounds\" class=\"settings g\">Deadlines & rounds</h3>\n"; echo '<p class="hint">Reviews are due by the deadline, but <em>cannot be modified</em> after the hard deadline. Most conferences don’t use hard deadlines for reviews.<br />', $sv->type_hint("date") ?: "", '</p>'; $rounds = $Conf->round_list(); if ($sv->use_req()) { for ($i = 1; isset($sv->req["roundname_{$i}"]); ++$i) { $rounds[$i] = get($sv->req, "deleteround_{$i}") ? ";" : trim(get_s($sv->req, "roundname_{$i}")); } } // prepare round selector $round_value = trim($sv->curv("rev_roundtag")); $current_round_value = $Conf->setting_data("rev_roundtag", ""); if (preg_match('/\\A(?:|\\(none\\)|\\(no name\\)|default|unnamed|#0)\\z/i', $round_value)) { $round_value = "#0"; } else { if (($round_number = $Conf->round_number($round_value, false)) || ($round_number = $Conf->round_number($current_round_value, false))) { $round_value = "#" . $round_number; } else { $round_value = $selector[$current_round_value] = $current_round_value; } } $round_map = edb_map(Dbl::ql("select reviewRound, count(*) from PaperReview group by reviewRound")); $print_round0 = true; if ($round_value !== "#0" && $round_value !== "" && $current_round_value !== "" && (!$sv->use_req() || isset($sv->req["roundname_0"])) && !$Conf->round0_defined()) { $print_round0 = false; } $selector = array(); if ($print_round0) { $selector["#0"] = "unnamed"; } for ($i = 1; $i < count($rounds); ++$i) { if ($rounds[$i] !== ";") { $selector["#{$i}"] = (object) array("label" => $rounds[$i], "id" => "rev_roundtag_{$i}"); } } echo '<div id="round_container"', count($selector) == 1 ? ' style="display:none"' : '', '>', '<table id="rev_roundtag_table"><tr><td class="lxcaption">', $sv->label("rev_roundtag", "Current round"), '</td><td>', Ht::select("rev_roundtag", $selector, $round_value, $sv->sjs("rev_roundtag")), '</td></tr></table>', '<div class="hint">This round is used for new assignments.</div><div class="g"></div></div>'; echo '<div id="roundtable">'; $num_printed = 0; for ($i = 0; $i < count($rounds); ++$i) { if ($i ? $rounds[$i] !== ";" : $print_round0) { $this->echo_round($sv, $i, $i ? $rounds[$i] : "", +get($round_map, $i), count($selector) !== 1); ++$num_printed; } } echo '</div><div id="newround" style="display:none">'; $this->echo_round($sv, '$', "", "", true); echo '</div><div class="g"></div>'; echo Ht::js_button("Add round", "review_round_settings.add();hiliter(this)"), ' <span class="hint"><a href="', hoturl("help", "t=revround"), '">What is this?</a></span>', Ht::hidden("oldroundcount", count($Conf->round_list())), Ht::hidden("has_rev_roundtag", 1); for ($i = 1; $i < count($rounds); ++$i) { if ($rounds[$i] === ";") { echo Ht::hidden("roundname_{$i}", "", array("id" => "roundname_{$i}")), Ht::hidden("deleteround_{$i}", 1); } } Ht::stash_script("review_round_settings.init()"); // External reviews echo "<h3 class=\"settings g\">External reviews</h3>\n"; echo "<div class='g'></div>"; $sv->echo_checkbox("extrev_chairreq", "PC chair must approve proposed external reviewers"); $sv->echo_checkbox("pcrev_editdelegate", "PC members can edit external reviews they requested"); echo "<div class='g'></div>\n"; $t = expandMailTemplate("requestreview", false); echo "<table id='foldmailbody_requestreview' class='", $t == expandMailTemplate("requestreview", true) ? "foldc" : "foldo", "'><tr><td>", foldbutton("mailbody_requestreview"), "</td>", "<td><a href='#' onclick='return fold(\"mailbody_requestreview\")' class='q'><strong>Mail template for external review requests</strong></a>", " <span class='fx'>(<a href='", hoturl("mail"), "'>keywords</a> allowed; set to empty for default)<br /></span>\n<textarea class='tt fx' name='mailbody_requestreview' cols='80' rows='20'>", htmlspecialchars($t["body"]), "</textarea>", "</td></tr></table>\n"; // Review visibility echo "<h3 class=\"settings g\">Visibility</h3>\n"; echo "Can PC members <strong>see all reviews</strong> except for conflicts?<br />\n"; $sv->echo_radio_table("pc_seeallrev", array(Conf::PCSEEREV_YES => "Yes", Conf::PCSEEREV_UNLESSINCOMPLETE => "Yes, unless they haven’t completed an assigned review for the same paper", Conf::PCSEEREV_UNLESSANYINCOMPLETE => "Yes, after completing all their assigned reviews", Conf::PCSEEREV_IFCOMPLETE => "Only after completing a review for the same paper")); echo "<div class='g'></div>\n"; echo "Can PC members see <strong>reviewer names</strong> except for conflicts?<br />\n"; $sv->echo_radio_table("pc_seeblindrev", array(0 => "Yes", 1 => "Only after completing a review for the same paper<br /><span class='hint'>This setting also hides reviewer-only comments from PC members who have not completed a review for the same paper.</span>")); echo "<div class='g'></div>"; echo "Can external reviewers see the other reviews for their assigned papers, once they’ve submitted their own?<br />\n"; $sv->echo_radio_table("extrev_view", array(2 => "Yes", 1 => "Yes, but they can’t see who wrote blind reviews", 0 => "No")); // Review ratings echo "<h3 class=\"settings g\">Review ratings</h3>\n"; echo "Should HotCRP collect ratings of reviews? <a class='hint' href='", hoturl("help", "t=revrate"), "'>(Learn more)</a><br />\n"; $sv->echo_radio_table("rev_ratings", array(REV_RATINGS_PC => "Yes, PC members can rate reviews", REV_RATINGS_PC_EXTERNAL => "Yes, PC members and external reviewers can rate reviews", REV_RATINGS_NONE => "No")); }