function perm_change_tag(PaperInfo $prow, $tag, $previndex, $index, $forceShow = null) { global $Conf; if ($this->can_change_tag($prow, $tag, $previndex, $index, $forceShow)) { return null; } $rights = $this->rights($prow, $forceShow); $whyNot = $prow->initial_whynot(); $whyNot["tag"] = $tag; if (!$this->isPC) { $whyNot["permission"] = true; } else { if ($rights->conflict_type > 0) { $whyNot["conflict"] = true; if ($rights->allow_administer) { $whyNot["forceShow"] = true; } } else { if (!$Conf->timePCViewPaper($prow, false)) { if ($prow->timeWithdrawn > 0) { $whyNot["withdrawn"] = true; } else { $whyNot["notSubmitted"] = true; } } else { $tag = TagInfo::base($tag); $twiddle = strpos($tag, "~"); if ($twiddle === 0 && $tag[1] === "~" || $twiddle > 0 && substr($tag, 0, $twiddle) != $this->contactId) { $whyNot["otherTwiddleTag"] = true; } else { if ($twiddle !== false) { $whyNot["voteTagNegative"] = true; } else { $t = TagInfo::defined_tag($tag); if ($t && $t->vote) { $whyNot["voteTag"] = true; } else { $whyNot["chairTag"] = true; } } } } } } return $whyNot; }
public function editable_tags(Contact $user) { $tags = $this->viewable_tags($user); if ($tags !== "") { $privChair = $user->allow_administer($this); $dt = TagInfo::defined_tags(); $etags = array(); foreach (explode(" ", $tags) as $t) { if (!($t === "" || ($v = $dt->check(TagInfo::base($t))) && ($v->vote || $v->approval || !$privChair && (!$user->privChair || !$v->sitewide) && ($v->chair || $v->rank)))) { $etags[] = $t; } } $tags = join(" ", $etags); } return $tags; }
function do_tags() { global $Conf, $Me, $papersel; // check tags $tagger = new Tagger($Me); $t1 = array(); $errors = array(); foreach (preg_split('/[\\s,]+/', (string) @$_REQUEST["tag"]) as $t) { if ($t === "") { /* nada */ } else { if (!($t = $tagger->check($t, Tagger::NOPRIVATE))) { $errors[] = $tagger->error_html; } else { if (TagInfo::base($t) === "pc") { $errors[] = "The “pc” user tag is set automatically for all PC members."; } else { $t1[] = $t; } } } } if (count($errors)) { return Conf::msg_error(join("<br>", $errors)); } else { if (!count($t1)) { return $Conf->warnMsg("Nothing to do."); } } // modify database Dbl::qe("lock tables ContactInfo write"); Conf::$no_invalidate_caches = true; $users = array(); if ($_REQUEST["tagtype"] === "s") { // erase existing tags $likes = array(); $removes = array(); foreach ($t1 as $t) { list($tag, $index) = TagInfo::split_index($t); $removes[] = $t; $likes[] = "contactTags like " . Dbl::utf8ci("'% " . sqlq_for_like($tag) . "#%'"); } foreach (Dbl::fetch_first_columns(Dbl::qe("select contactId from ContactInfo where " . join(" or ", $likes))) as $cid) { $users[(int) $cid] = (object) array("id" => (int) $cid, "add_tags" => [], "remove_tags" => $removes); } } // account for request $key = $_REQUEST["tagtype"] === "d" ? "remove_tags" : "add_tags"; foreach ($papersel as $cid) { if (!isset($users[(int) $cid])) { $users[(int) $cid] = (object) array("id" => (int) $cid, "add_tags" => [], "remove_tags" => []); } $users[(int) $cid]->{$key} = array_merge($users[(int) $cid]->{$key}, $t1); } // apply modifications foreach ($users as $cid => $cj) { $us = new UserStatus(array("send_email" => false)); if (!$us->save($cj)) { $errors = array_merge($errors, $us->error_messages()); } } Dbl::qe("unlock tables"); Conf::$no_invalidate_caches = false; $Conf->invalidateCaches(["pc" => true]); // report if (!count($errors)) { $Conf->confirmMsg("Tags saved."); redirectSelf(array("tagact" => null, "tag" => null)); } else { Conf::msg_error(join("<br>", $errors)); } }
function run(Contact $user, $qreq, $ssel) { global $Conf; $papers = $ssel->selection(); $act = $qreq->tagfn; $tagreq = trim(str_replace(",", " ", (string) $qreq->tag)); $tags = preg_split('/\\s+/', $tagreq); if ($act == "da") { $otags = $tags; foreach ($otags as $t) { $tags[] = "all~" . preg_replace(',\\A.*~([^~]+)\\z', '$1', $t); } $act = "d"; } else { if ($act == "sor") { shuffle($papers); } } $x = array("action,paper,tag\n"); if ($act == "s" || $act == "so" || $act == "sos" || $act == "sor") { foreach ($tags as $t) { $x[] = "cleartag,all," . TagInfo::base($t) . "\n"; } } if ($act == "s" || $act == "a") { $action = "tag"; } else { if ($act == "d") { $action = "cleartag"; } else { if ($act == "so" || $act == "sor" || $act == "ao") { $action = "nexttag"; } else { if ($act == "sos" || $act == "aos") { $action = "seqnexttag"; } else { $action = null; } } } } $assignset = new AssignmentSet($user, $user->privChair); if (count($papers) && $action) { foreach ($papers as $p) { foreach ($tags as $t) { $x[] = "{$action},{$p},{$t}\n"; } } $assignset->parse(join("", $x)); } else { if (count($papers) && $act == "cr" && $user->privChair) { $source_tag = trim((string) $qreq->tagcr_source); if ($source_tag == "") { $source_tag = substr($tagreq, 0, 2) == "~~" ? substr($tagreq, 2) : $tagreq; } $tagger = new Tagger($user); if ($tagger->check($tagreq, Tagger::NOPRIVATE | Tagger::NOVALUE) && $tagger->check($source_tag, Tagger::NOPRIVATE | Tagger::NOCHAIR | Tagger::NOVALUE)) { $r = new PaperRank($source_tag, $tagreq, $papers, $qreq->tagcr_gapless, "Search", "search"); $r->run($qreq->tagcr_method); $r->apply($assignset); $assignset->finish(); if ($qreq->q === "") { $qreq->q = "order:{$tagreq}"; } } else { $assignset->error($tagger->error_html); } } } if ($errors = join("<br />\n", $assignset->errors_html())) { if ($assignset->has_assigners()) { Conf::msg_warning("Some tag assignments were ignored:<br />\n{$errors}"); $assignset->clear_errors(); } else { Conf::msg_error($errors); } } $success = $assignset->execute(); if (!$Conf->headerPrinted && $qreq->ajax) { $Conf->ajaxExit(array("ok" => $success)); } else { if (!$Conf->headerPrinted && $success) { if (!$errors) { $Conf->confirmMsg("Tags saved."); } $args = array("atab" => "tag"); foreach (array("tag", "tagfn", "tagcr_method", "tagcr_source", "tagcr_gapless") as $arg) { if (isset($qreq[$arg])) { $args[$arg] = $qreq[$arg]; } } redirectSelf($args); } } }
function content($fieldId, $row) { global $Conf; switch ($fieldId) { case self::FIELD_NAME: $t = Text::name_html($row); if (trim($t) == "") { $t = "[No name]"; } $t = '<span class="taghl">' . $t . '</span>'; if ($this->contact->privChair) { $t = "<a href=\"" . hoturl("profile", "u=" . urlencode($row->email) . $this->contactLinkArgs) . "\"" . ($row->disabled ? " class='uu'" : "") . ">{$t}</a>"; } if ($row->roles & Contact::ROLE_CHAIR) { $t .= ' <span class="pcrole">(chair)</span>'; } else { if (($row->roles & (Contact::ROLE_ADMIN | Contact::ROLE_PC)) == (Contact::ROLE_ADMIN | Contact::ROLE_PC)) { $t .= ' <span class="pcrole">(PC, sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_ADMIN) { $t .= ' <span class="pcrole">(sysadmin)</span>'; } else { if ($row->roles & Contact::ROLE_PC && $this->limit != "pc") { $t .= ' <span class="pcrole">(PC)</span>'; } } } } if ($this->contact->privChair && $row->email != $this->contact->email) { $t .= " <a href=\"" . hoturl("index", "actas=" . urlencode($row->email)) . "\">" . Ht::img("viewas.png", "[Act as]", array("title" => "Act as " . Text::name_text($row))) . "</a>"; } if ($row->disabled && $this->contact->isPC) { $t .= ' <span class="hint">(disabled)</span>'; } return $t; case self::FIELD_EMAIL: if (!$this->contact->isPC) { return ""; } $e = htmlspecialchars($row->email); if (strpos($row->email, "@") === false) { return $e; } else { return "<a href=\"mailto:{$e}\">{$e}</a>"; } case self::FIELD_AFFILIATION: case self::FIELD_AFFILIATION_ROW: return htmlspecialchars($row->affiliation); case self::FIELD_LASTVISIT: if (!$row->lastLogin) { return "Never"; } return $Conf->printableTimeShort($row->lastLogin); case self::FIELD_SELECTOR: case self::FIELD_SELECTOR_ON: $this->any->sel = true; $c = ""; if ($fieldId == self::FIELD_SELECTOR_ON) { $c = " checked='checked'"; } return "<input type='checkbox' class='cb' name='pap[]' value='{$row->contactId}' tabindex='1' id='psel{$this->count}' onclick='rangeclick(event,this)' {$c}/>"; case self::FIELD_HIGHTOPICS: case self::FIELD_LOWTOPICS: if (!defval($row, "topicIds")) { return ""; } $wanthigh = $fieldId == self::FIELD_HIGHTOPICS; $topics = array_combine(explode(",", $row->topicIds), explode(",", $row->topicInterest)); $nt = $nti = array(); foreach ($topics as $k => $v) { if ($wanthigh ? $v > 0 : $v < 0) { $nt[] = $k; $nti[] = $v; } } if (count($nt)) { return PaperInfo::unparse_topic_list_html($nt, $nti, true); } else { return ""; } case self::FIELD_REVIEWS: if (!$row->numReviews && !$row->numReviewsSubmitted) { return ""; } $a1 = "<a href=\"" . hoturl("search", "t=s&q=re:" . urlencode($row->email)) . "\">"; if ($row->numReviews == $row->numReviewsSubmitted) { return "{$a1}<b>{$row->numReviewsSubmitted}</b></a>"; } else { return "{$a1}<b>{$row->numReviewsSubmitted}</b>/{$row->numReviews}</a>"; } case self::FIELD_LEADS: if (!$row->numLeads) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=lead:" . urlencode($row->email)) . "\">{$row->numLeads}</a>"; case self::FIELD_SHEPHERDS: if (!$row->numShepherds) { return ""; } return "<a href=\"" . hoturl("search", "t=s&q=shepherd:" . urlencode($row->email)) . "\">{$row->numShepherds}</a>"; case self::FIELD_REVIEW_RATINGS: if (!$row->numReviews && !$row->numReviewsSubmitted || !$row->numRatings) { return ""; } $a = array(); $b = array(); if ($row->sumRatings > 0) { $a[] = $row->sumRatings . " positive"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:%2B") . "\">+" . $row->sumRatings . "</a>"; } if ($row->sumRatings < $row->numRatings) { $a[] = $row->numRatings - $row->sumRatings . " negative"; $b[] = "<a href=\"" . hoturl("search", "q=re:" . urlencode($row->email) . "+rate:-") . "\">−" . ($row->numRatings - $row->sumRatings) . "</a>"; } return "<span class='hastitle' title='" . join(", ", $a) . "'>" . join(" ", $b) . "</span>"; case self::FIELD_PAPERS: if (!$row->paperIds) { return ""; } $x = explode(",", $row->paperIds); sort($x, SORT_NUMERIC); foreach ($x as &$v) { $v = '<a href="' . hoturl("paper", "p={$v}") . '">' . $v . '</a>'; } $ls = "p/s/"; if ($this->limit == "auuns" || $this->limit == "all") { $ls = "p/all/"; } $ls = htmlspecialchars($ls . urlencode("au:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $x) . '</div>'; case self::FIELD_REVIEW_PAPERS: if (!$row->paperIds) { return ""; } $pids = explode(",", $row->paperIds); $rids = explode(",", $row->reviewIds); $ords = explode(",", $row->reviewOrdinals); $spids = $pids; sort($spids, SORT_NUMERIC); $m = array(); for ($i = 0; $i != count($pids); ++$i) { if ($ords[$i]) { $url = hoturl("paper", "p=" . $pids[$i] . "#r" . $pids[$i] . unparseReviewOrdinal($ords[$i])); } else { $url = hoturl("review", "p=" . $pids[$i] . "&r=" . $rids[$i]); } $m[$pids[$i]] = "<a href=\"{$url}\">" . $pids[$i] . "</a>"; } ksort($m, SORT_NUMERIC); $ls = htmlspecialchars("p/s/" . urlencode("re:" . $row->email)); return '<div class="has_hotcrp_list" data-hotcrp-list="' . $ls . '">' . join(", ", $m) . '</div>'; case self::FIELD_TAGS: if ($this->contact->isPC && ($tags = $row->viewable_tags($this->contact))) { $x = []; foreach (TagInfo::split($tags) as $t) { $x[] = '<a class="qq nw" href="' . hoturl("users", "t=%23" . TagInfo::base($t)) . '">' . $this->tagger->unparse_hashed($t) . '</a>'; } return join(" ", $x); } return ""; case self::FIELD_COLLABORATORS: if (!$this->contact->isPC || !($row->roles & Contact::ROLE_PC)) { return ""; } $t = array(); foreach (explode("\n", $row->collaborators) as $collab) { if (preg_match(',\\A(.*?)\\s*(\\(.*\\))\\s*\\z,', $collab, $m)) { $t[] = '<span class="nw">' . htmlspecialchars($m[1]) . ' <span class="auaff">' . htmlspecialchars($m[2]) . '</span></span>'; } else { if (($collab = trim($collab)) !== "" && strcasecmp($collab, "None")) { $t[] = '<span class="nw">' . htmlspecialchars($collab) . '</span>'; } } } return join("; ", $t); default: $f = ReviewForm::field($fieldId); if (!$f) { return ""; } if (!($row->roles & Contact::ROLE_PC) && !$this->contact->privChair && $this->limit != "req") { return ""; } $v = scoreCounts($row->{$fieldId}, $this->scoreMax[$fieldId]); $m = ""; if ($v->n > 0) { $m = $f->unparse_graph($v, 2, 0); } return $m; } }
public function unparse_and_link($viewable, $alltags, $highlight = false) { $vtags = $this->unparse($viewable); if ($vtags === "") { return ""; } // decorate with URL matches $tt = ""; // clean $highlight $byhighlight = array(); $anyhighlight = false; assert($highlight === false || is_array($highlight)); if ($highlight) { foreach ($highlight as $h) { $tag = is_object($h) ? $h->tag : $h; if (($pos = strpos($tag, "~")) !== false) { $tag = substr($tag, $pos); } $byhighlight[strtolower($tag)] = ""; } } foreach (preg_split('/\\s+/', $vtags) as $tag) { if (!($base = TagInfo::base($tag))) { continue; } $lbase = strtolower($base); if ($link = $this->link($tag)) { $tx = '<a class="qq nw" href="' . $link . '">#' . $base . '</a>'; } else { $tx = "#" . $base; } $tx .= substr($tag, strlen($base)); if (isset($byhighlight[$lbase])) { $byhighlight[$lbase] .= "<strong>" . $tx . "</strong> "; $anyhighlight = true; } else { $tt .= $tx . " "; } } if ($anyhighlight) { return rtrim(join("", $byhighlight) . $tt); } else { return rtrim($tt); } }