private function apply_remove($pid, $contact, AssignmentState $state, $m) { $prow = $state->prow($pid); // resolve twiddle portion if ($m[1] && $m[1] != "~~" && !ctype_digit(substr($m[1], 0, strlen($m[1]) - 1))) { $c = substr($m[1], 0, strlen($m[1]) - 1); $twiddlecids = ContactSearch::make_pc($c, $state->contact->contactId)->ids; if (count($twiddlecids) == 0) { return "“" . htmlspecialchars($c) . "” doesn’t match a PC member."; } else { if (count($twiddlecids) == 1) { $m[1] = $twiddlecids[0] . "~"; } else { $m[1] = "(?:" . join("|", $twiddlecids) . ")~"; } } } // resolve tag portion $search_ltag = null; if (strcasecmp($m[2], "none") == 0) { return; } else { if (strcasecmp($m[2], "any") == 0 || strcasecmp($m[2], "all") == 0) { if ($m[1]) { $m[2] = "[^~]*"; } else { if ($state->contact->privChair) { $m[2] = "(?:~~|" . $state->contact->contactId . "~|)[^~]*"; } else { $m[2] = "(?:" . $state->contact->contactId . "~|)[^~]*"; } } } else { if (!preg_match(',[*(],', $m[1] . $m[2])) { $search_ltag = $m[1] . $m[2]; } $m[2] = str_replace("\\*", "[^~]*", preg_quote($m[2])); } } // resolve index comparator if (preg_match(',\\A(?:any|all|none|clear)\\z,i', $m[4])) { $m[3] = $m[4] = ""; } else { if ($m[3] == "#") { $m[3] = "="; } $m[4] = cvtint($m[4], 0); } // if you can't view the tag, you can't clear the tag // (information exposure) if ($search_ltag && !$state->contact->can_view_tag($prow, $search_ltag, $state->override)) { return $this->cannot_view_error($state, $pid, $search_ltag); } // query $res = $state->query(array("type" => "tag", "pid" => $pid, "ltag" => $search_ltag)); $tag_re = '{\\A' . $m[1] . $m[2] . '\\z}i'; $vote_adjustments = array(); foreach ($res as $x) { if (preg_match($tag_re, $x["ltag"]) && (!$m[3] || CountMatcher::compare($x["_index"], $m[3], $m[4])) && ($search_ltag || $state->contact->can_change_tag($prow, $x["ltag"], $x["_index"], null, $state->override))) { $state->remove($x); if ($v = TagInfo::votish_base($x["ltag"])) { $vote_adjustments[$v] = true; } } } foreach ($vote_adjustments as $vtag => $v) { $this->account_votes($pid, $vtag, $state); } }