public function table_html($listname, $options = array())
 {
     global $Conf;
     if (!$this->_prepare()) {
         return null;
     }
     if (isset($options["fold"])) {
         foreach ($options["fold"] as $n => $v) {
             $this->viewmap->{$n} = $v;
         }
     }
     if (isset($options["table_id"])) {
         $this->viewmap->table_id = $options["table_id"];
     }
     // need tags for row coloring
     if ($this->contact->can_view_tags(null)) {
         $this->qopts["tags"] = 1;
     }
     $this->table_type = $listname;
     // get column list, check sort
     $field_list = $this->_list_columns($listname);
     if (!$field_list) {
         Conf::msg_error("There is no paper list query named “" . htmlspecialchars($listname) . "”.");
         return null;
     }
     $field_list = $this->_columns($field_list, true);
     $body_attr = $this->row_attr;
     $rows = $this->_rows($field_list);
     if ($rows === null) {
         return null;
     }
     // return IDs if requested
     if (empty($rows)) {
         if ($altq = $this->search->alternate_query()) {
             $altqh = htmlspecialchars($altq);
             $url = $this->search->url_site_relative_raw($altq);
             if (substr($url, 0, 5) == "search") {
                 $altqh = "<a href=\"" . htmlspecialchars(Navigation::siteurl() . $url) . "\">" . $altqh . "</a>";
             }
             return "No matching papers. Did you mean “{$altqh}”?";
         } else {
             return "No matching papers";
         }
     }
     // get field array
     $fieldDef = array();
     $ncol = $titlecol = 0;
     // folds: au:1, anonau:2, fullrow:3, aufull:4, force:5, rownum:6, [fields]
     $next_fold = 7;
     foreach ($field_list as $fdef) {
         if ($fdef->view != Column::VIEW_NONE) {
             $fieldDef[] = $fdef;
         }
         if ($fdef->view != Column::VIEW_NONE && $fdef->foldable) {
             $fdef->foldable = $next_fold;
             ++$next_fold;
         }
         if ($fdef->name == "title") {
             $titlecol = $ncol;
         }
         if ($fdef->view == Column::VIEW_COLUMN && !$fdef->is_folded) {
             ++$ncol;
         }
     }
     // count non-callout columns
     $skipcallout = 0;
     foreach ($fieldDef as $fdef) {
         if ($fdef->name != "id" && !isset($fdef->is_selector)) {
             break;
         } else {
             ++$skipcallout;
         }
     }
     // create render state
     $rstate = new PaperListRenderState($ncol, $titlecol, $skipcallout);
     // collect row data
     $body = array();
     $lastheading = !empty($this->search->groupmap) ? -1 : -2;
     $need_render = false;
     foreach ($rows as $row) {
         ++$this->count;
         if ($lastheading > -2) {
             $lastheading = $this->_check_heading($this->_row_thenval($row), $rstate, $rows, $lastheading, $body);
         }
         $body[] = $this->_row_text($rstate, $row, $fieldDef);
         if ($this->need_render && !$need_render) {
             $Conf->footerScript('$(plinfo.render_needed)', 'plist_render_needed');
             $need_render = true;
         }
         if ($this->need_render && $this->count % 16 == 15) {
             $body[count($body) - 1] .= "  <script>plinfo.render_needed()</script>\n";
             $this->need_render = false;
         }
     }
     if ($lastheading > -2 && $this->search->is_order_anno) {
         while ($lastheading + 1 < count($this->search->groupmap)) {
             $lastheading = $this->_check_heading($lastheading + 1, $rstate, $rows, $lastheading, $body);
         }
     }
     // header cells
     $colhead = "";
     $url = $this->search->url_site_relative_raw();
     if (!defval($options, "noheader")) {
         $colhead .= " <thead class=\"pltable\">\n  <tr class=\"pl_headrow\">";
         $ord = 0;
         $titleextra = $this->_make_title_header_extra($rstate, $fieldDef, get($options, "header_links"));
         foreach ($fieldDef as $fdef) {
             if ($fdef->view != Column::VIEW_COLUMN || $fdef->is_folded) {
                 continue;
             }
             $colhead .= "<th class=\"pl " . $fdef->className;
             if ($fdef->foldable) {
                 $colhead .= " fx" . $fdef->foldable;
             }
             $colhead .= "\">";
             if ($fdef->has_content) {
                 $colhead .= $this->_field_title($fdef, $ord);
             }
             if ($titleextra && $fdef->className == "pl_title") {
                 $colhead .= $titleextra;
                 $titleextra = false;
             }
             $colhead .= "</th>";
             ++$ord;
         }
         $colhead .= "</tr>\n";
         if ($this->search->is_order_anno) {
             $colhead .= "  <tr class=\"pl_headrow pl_annorow\" data-anno-tag=\"{$this->search->is_order_anno}\">";
             if ($rstate->titlecol) {
                 $colhead .= "<td colspan=\"{$rstate->titlecol}\"></td>";
             }
             $colhead .= "<td colspan=\"" . ($rstate->ncol - $rstate->titlecol) . "\"><a href=\"#\" onclick=\"return plinfo_tags.edit_anno(this)\">Annotate order</a></td></tr>\n";
         }
         $colhead .= " </thead>\n";
     }
     // table skeleton including fold classes
     $foldclasses = array();
     if ($this->foldable) {
         $foldclasses = $this->_analyze_folds($rstate, $fieldDef);
     }
     $enter = "";
     if (self::$include_stash) {
         $enter .= Ht::take_stash();
     }
     $enter .= "<table class=\"pltable plt_" . htmlspecialchars($listname);
     if (defval($options, "class")) {
         $enter .= " " . $options["class"];
     }
     if ($this->listNumber) {
         $enter .= " has_hotcrp_list";
     }
     if (!empty($foldclasses)) {
         $enter .= " " . join(" ", $foldclasses);
     }
     if ($this->viewmap->table_id) {
         $enter .= "\" id=\"" . $this->viewmap->table_id;
     }
     if (defval($options, "attributes")) {
         foreach ($options["attributes"] as $n => $v) {
             $enter .= "\" {$n}=\"" . htmlspecialchars($v);
         }
     }
     if ($this->search->is_order_anno) {
         $enter .= "\" data-order-tag=\"{$this->search->is_order_anno}";
     }
     foreach ($body_attr as $k => $v) {
         $enter .= "\" {$k}=\"" . htmlspecialchars($v);
     }
     if ($this->listNumber) {
         $enter .= '" data-hotcrp-list="' . $this->listNumber;
     }
     $enter .= "\" data-fold=\"true\">\n";
     $exit = "</table>";
     // maybe make columns, maybe not
     $tbody_class = "pltable";
     if ($this->viewmap->columns && !empty($rstate->ids) && $this->_column_split($rstate, $colhead, $body)) {
         $enter = '<div class="plsplit_col_ctr_ctr"><div class="plsplit_col_ctr">' . $enter;
         $exit = $exit . "</div></div>";
         $ncol = $rstate->split_ncol;
         $tbody_class = "pltable_split";
     } else {
         $enter .= $colhead;
         $tbody_class .= $rstate->hascolors ? " pltable_colored" : "";
     }
     // footer
     $foot = "";
     if ($this->viewmap->statistics && !$this->viewmap->columns) {
         $foot .= $this->_statistics_rows($rstate, $fieldDef);
     }
     if ($fieldDef[0] instanceof SelectorPaperColumn && !defval($options, "nofooter")) {
         $foot .= $this->_footer($ncol, get_s($options, "footer_extra"));
     }
     if ($foot) {
         $enter .= ' <tfoot' . ($rstate->hascolors ? ' class="pltable_colored"' : "") . ">\n" . $foot . " </tfoot>\n";
     }
     // body
     $enter .= " <tbody class=\"{$tbody_class}\">\n";
     // header scripts to set up delegations
     if ($this->_header_script) {
         $enter .= '  <script>' . $this->_header_script . "</script>\n";
     }
     // session variable to remember the list
     if ($this->listNumber) {
         $sl = $this->search->create_session_list_object($rstate->ids, self::_listDescription($listname), $this->sortdef());
         if (isset($this->qreq->sort)) {
             $url .= (strpos($url, "?") ? "&" : "?") . "sort=" . urlencode($this->qreq->sort);
         }
         $sl->url = $url;
         if (get($options, "list_properties")) {
             foreach ($options["list_properties"] as $k => $v) {
                 $sl->{$k} = $v;
             }
         }
         SessionList::change($this->listNumber, $sl);
     }
     foreach ($fieldDef as $fdef) {
         if ($fdef->has_content) {
             $this->any[$fdef->name] = true;
         }
     }
     if ($rstate->has_openau) {
         $this->any->openau = true;
     }
     if ($rstate->has_anonau) {
         $this->any->anonau = true;
     }
     $this->ids = $rstate->ids;
     return $enter . join("", $body) . " </tbody>\n" . $exit;
 }
 function footer()
 {
     global $Opt, $Me, $ConfSitePATH;
     echo "</div>\n", "<div id='footer'>\n  <div id='footer_crp'>", defval($Opt, "extraFooter", ""), "<a href='http://read.seas.harvard.edu/~kohler/hotcrp/'>HotCRP</a>";
     if (!defval($Opt, "noFooterVersion", 0)) {
         if ($Me && $Me->privChair) {
             echo " v", HOTCRP_VERSION;
             if (is_dir("{$ConfSitePATH}/.git")) {
                 $args = array();
                 exec("export GIT_DIR=" . escapeshellarg($ConfSitePATH) . "/.git; git rev-parse HEAD 2>/dev/null; git rev-parse v" . HOTCRP_VERSION . " 2>/dev/null", $args);
                 if (count($args) == 2 && $args[0] != $args[1]) {
                     echo " [", substr($args[0], 0, 7), "...]";
                 }
             }
         } else {
             echo "<!-- Version ", HOTCRP_VERSION, " -->";
         }
     }
     echo "</div>\n  <hr class=\"c\" /></div>\n";
     echo Ht::take_stash(), "</body>\n</html>\n";
 }
 public function run()
 {
     global $Conf, $Me, $Qreq, $SSel, $pcsel, $badpairs, $scoreselector;
     assert($this->ok);
     session_write_close();
     // this might take a long time
     set_time_limit(240);
     // prepare autoassigner
     if ($Qreq->seed && is_numeric($Qreq->seed)) {
         srand((int) $Qreq->seed);
     }
     $this->autoassigner = $autoassigner = new Autoassigner($SSel->selection());
     if ($Qreq->pctyp === "sel") {
         $n = $autoassigner->select_pc(array_keys($pcsel));
         if ($n == 0) {
             Conf::msg_error("Select one or more PC members to assign.");
             return null;
         }
     }
     if ($Qreq->balance === "all") {
         $autoassigner->set_balance(Autoassigner::BALANCE_ALL);
     }
     foreach ($badpairs as $cid1 => $bp) {
         foreach ($bp as $cid2 => $x) {
             $autoassigner->avoid_pair_assignment($cid1, $cid2);
         }
     }
     if ($Qreq->method === "random") {
         $autoassigner->set_method(Autoassigner::METHOD_RANDOM);
     } else {
         $autoassigner->set_method(Autoassigner::METHOD_MCMF);
     }
     $autoassigner->add_progressf(array($this, "progress"));
     $this->live = true;
     echo '<div id="propass" class="propass">';
     $this->start_at = microtime(true);
     if ($this->atype === "prefconflict") {
         $autoassigner->run_prefconflict($Qreq->t);
     } else {
         if ($this->atype === "clear") {
             $autoassigner->run_clear($this->reviewtype);
         } else {
             if ($this->atype === "lead" || $this->atype === "shepherd") {
                 $autoassigner->run_paperpc($this->atype, $Qreq["{$this->atype}score"]);
             } else {
                 if ($this->atype === "revpc") {
                     $autoassigner->run_reviews_per_pc($this->reviewtype, $Qreq->rev_roundtag, cvtint($Qreq->revpcct));
                 } else {
                     if ($this->atype === "revadd") {
                         $autoassigner->run_more_reviews($this->reviewtype, $Qreq->rev_roundtag, cvtint($Qreq->revaddct));
                     } else {
                         if ($this->atype === "rev") {
                             $autoassigner->run_ensure_reviews($this->reviewtype, $Qreq->rev_roundtag, cvtint($Qreq->revct));
                         } else {
                             if ($this->atype === "discorder") {
                                 $autoassigner->run_discussion_order($this->discordertag);
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($this->live) {
         echo $this->result_html(), "</div>\n";
     } else {
         PaperList::$include_stash = false;
         $result_html = $this->result_html();
         echo Ht::take_stash(), '<script>$$("propass").innerHTML=', json_encode($result_html), ";</script>\n";
     }
     if ($this->autoassigner->assignments()) {
         $Conf->footer();
         exit;
     }
 }
Beispiel #4
0
 function footer()
 {
     global $Me, $ConfSitePATH;
     echo "</div>\n", "<div id='footer'>\n";
     $footy = $this->opt("extraFooter", "");
     if (false) {
         $footy .= "<a href='http://read.seas.harvard.edu/~kohler/hotcrp/'>HotCRP</a> Conference Management Software";
     }
     if (!$this->opt("noFooterVersion")) {
         if ($Me && $Me->privChair) {
             if (is_dir("{$ConfSitePATH}/.git")) {
                 $args = array();
                 exec("export GIT_DIR=" . escapeshellarg($ConfSitePATH) . "/.git; git rev-parse HEAD 2>/dev/null", $args);
                 if (count($args) == 2 && $args[0] != $args[1]) {
                     $footy .= " [" . substr($args[0], 0, 7) . "...]";
                 }
             }
         }
     }
     if ($footy) {
         echo "<div id='footer_crp'>{$footy}</div>";
     }
     echo "<div class='clear'></div></div>\n";
     echo Ht::take_stash(), "</body>\n</html>\n";
 }