예제 #1
0
function pcMembers()
{
    global $Conf, $Opt, $PcMembersCache;
    if (!@$PcMembersCache || $Conf->setting("pc") <= 0 || $PcMembersCache[0] < $Conf->setting("pc") || $PcMembersCache[1] != @$Opt["sortByLastName"]) {
        $pc = array();
        $result = Dbl::q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where (roles&" . Contact::ROLE_PC . ")!=0");
        $by_name_text = array();
        $pctags = array("pc" => "pc");
        while ($result && ($row = Contact::fetch($result))) {
            $pc[$row->contactId] = $row;
            if ($row->firstName || $row->lastName) {
                $name_text = Text::name_text($row);
                if (isset($by_name_text[$name_text])) {
                    $row->nameAmbiguous = $by_name_text[$name_text]->nameAmbiguous = true;
                }
                $by_name_text[$name_text] = $row;
            }
            if ($row->contactTags) {
                foreach (explode(" ", $row->contactTags) as $t) {
                    list($tag, $value) = TagInfo::split_index($t);
                    if ($tag) {
                        $pctags[strtolower($tag)] = $tag;
                    }
                }
            }
        }
        uasort($pc, "Contact::compare");
        ksort($pctags);
        $order = 0;
        foreach ($pc as $row) {
            $row->sort_position = $order;
            ++$order;
        }
        $PcMembersCache = array($Conf->setting("pc"), @$Opt["sortByLastName"], $pc, $pctags);
    }
    return $PcMembersCache[2];
}
예제 #2
0
 function save_json($cj, $actor, $send)
 {
     global $Conf, $Me, $Now;
     $inserting = !$this->contactId;
     $old_roles = $this->roles;
     $old_email = $this->email;
     $different_email = strtolower($cj->email) !== strtolower((string) $old_email);
     $cu = new Contact_Update($inserting, $different_email);
     $aupapers = null;
     if ($different_email) {
         $aupapers = self::email_authored_papers($cj->email, $cj);
     }
     // check whether this user is changing themselves
     $changing_other = false;
     if (self::contactdb() && $Me && (strcasecmp($this->email, $Me->email) != 0 || $Me->is_actas_user())) {
         $changing_other = true;
     }
     // Main fields
     foreach (array("firstName", "lastName", "email", "affiliation", "collaborators", "preferredEmail", "country") as $k) {
         if (isset($cj->{$k})) {
             $this->_save_assign_field($k, $cj->{$k}, $cu);
         }
     }
     if (isset($cj->phone)) {
         $this->_save_assign_field("voicePhoneNumber", $cj->phone, $cu);
     }
     $this->_save_assign_field("unaccentedName", Text::unaccented_name($this->firstName, $this->lastName), $cu);
     self::set_sorter($this);
     // Disabled
     $disabled = $this->disabled ? 1 : 0;
     if (isset($cj->disabled)) {
         $disabled = $cj->disabled ? 1 : 0;
     }
     if (($this->disabled ? 1 : 0) !== $disabled || !$this->contactId) {
         $cu->qv["disabled"] = $this->disabled = $disabled;
     }
     // Data
     $old_datastr = $this->data_str();
     $data = (object) array();
     foreach (array("address", "city", "state", "zip") as $k) {
         if (isset($cj->{$k}) && ($x = $cj->{$k})) {
             while (is_array($x) && $x[count($x) - 1] === "") {
                 array_pop($x);
             }
             $data->{$k} = $x ?: null;
         }
     }
     $this->merge_data($data);
     $datastr = $this->data_str();
     if ($datastr !== $old_datastr) {
         $cu->qv["data"] = $datastr;
     }
     // Changes to the above fields also change the updateTime.
     if (count($cu->qv)) {
         $cu->qv["updateTime"] = $this->updateTime = $Now;
     }
     // Follow
     if (isset($cj->follow)) {
         $w = 0;
         if (get($cj->follow, "reviews")) {
             $w |= WATCH_COMMENT;
         }
         if (get($cj->follow, "allreviews")) {
             $w |= WATCH_ALLCOMMENTS;
         }
         if (get($cj->follow, "allfinal")) {
             $w |= WATCHTYPE_FINAL_SUBMIT << WATCHSHIFT_ALL;
         }
         $this->_save_assign_field("defaultWatch", $w, $cu);
     }
     // Tags
     if (isset($cj->tags)) {
         $tags = array();
         foreach ($cj->tags as $t) {
             list($tag, $value) = TagInfo::split_index($t);
             if (strcasecmp($tag, "pc") != 0) {
                 $tags[$tag] = $tag . "#" . ($value ?: 0);
             }
         }
         ksort($tags);
         $t = count($tags) ? " " . join(" ", $tags) . " " : "";
         $this->_save_assign_field("contactTags", $t, $cu);
     }
     // If inserting, set initial password and creation time
     if ($inserting) {
         $cu->qv["creationTime"] = $this->creationTime = $Now;
         $this->_create_password(self::contactdb_find_by_email($this->email), $cu);
     }
     // Initial save
     if (count($cu->qv)) {
         // always true if $inserting
         $q = ($inserting ? "insert into" : "update") . " ContactInfo set " . join("=?, ", array_keys($cu->qv)) . "=?" . ($inserting ? "" : " where contactId={$this->contactId}");
         if (!($result = Dbl::qe_apply($Conf->dblink, $q, array_values($cu->qv)))) {
             return $result;
         }
         if ($inserting) {
             $this->contactId = $this->cid = (int) $result->insert_id;
         }
         Dbl::free($result);
     }
     // Topics
     if (isset($cj->topics)) {
         $tf = array();
         foreach ($cj->topics as $k => $v) {
             $tf[] = "({$this->contactId},{$k},{$v})";
         }
         $Conf->qe("delete from TopicInterest where contactId={$this->contactId}");
         if (count($tf)) {
             $Conf->qe("insert into TopicInterest (contactId,topicId,interest) values " . join(",", $tf));
         }
     }
     // Roles
     $roles = 0;
     if (isset($cj->roles)) {
         $roles = self::parse_roles_json($cj->roles);
         if ($roles !== $old_roles) {
             $this->save_roles($roles, $actor);
         }
     }
     // Update authorship
     if ($aupapers) {
         $this->save_authored_papers($aupapers);
     }
     // Update contact database
     $cdbu = $this->contactDbId ? $this : $this->contactdb_user_;
     if ($different_email) {
         $cdbu = null;
     }
     if (($cdb = self::contactdb()) && (!$cdbu || count($cu->cdb_uqv))) {
         $qv = [];
         if (!$cdbu) {
             $q = "insert into ContactInfo set firstName=?, lastName=?, email=?, affiliation=?, country=?, collaborators=?";
             $qv = array($this->firstName, $this->lastName, $this->email, $this->affiliation, $this->country, $this->collaborators);
             if ($this->password !== "" && ($this->password[0] !== " " || $this->password[1] === "\$")) {
                 $q .= ", password=?";
                 $qv[] = $this->password;
             }
             $q .= " on duplicate key update ";
         } else {
             $q = "update ContactInfo set ";
         }
         if (count($cu->cdb_uqv) && $changing_other) {
             $q .= join(", ", array_map(function ($k) {
                 return "{$k}=if(coalesce({$k},'')='',?,{$k})";
             }, array_keys($cu->cdb_uqv)));
         } else {
             if (count($cu->cdb_uqv)) {
                 $q .= join("=?, ", array_keys($cu->cdb_uqv)) . "=?";
             } else {
                 $q .= "firstName=firstName";
             }
         }
         if (count($cu->cdb_uqv)) {
             $q .= ", updateTime={$Now}";
         }
         $qv = array_merge($qv, array_values($cu->cdb_uqv));
         if ($cdbu) {
             $q .= " where contactDbId=" . $cdbu->contactDbId;
         }
         $result = Dbl::ql_apply($cdb, $q, $qv);
         Dbl::free($result);
         $this->contactdb_user_ = false;
     }
     // Password
     if (isset($cj->new_password)) {
         $this->change_password(get($cj, "old_password"), $cj->new_password, 0);
     }
     // Beware PC cache
     if (($roles | $old_roles) & Contact::ROLE_PCLIKE) {
         $Conf->invalidateCaches(array("pc" => 1));
     }
     // Mark creation and activity
     if ($inserting) {
         if ($send && !$this->disabled) {
             $this->sendAccountInfo("create", false);
         }
         $type = $this->disabled ? "disabled " : "";
         if ($Me && $Me->has_email() && $Me->email !== $this->email) {
             $Conf->log("Created {$type}account ({$Me->email})", $this);
         } else {
             $Conf->log("Created {$type}account", $this);
         }
     }
     $actor = $actor ?: $Me;
     if ($actor && $this->contactId == $actor->contactId) {
         $this->mark_activity();
     }
     return true;
 }
예제 #3
0
 private function parse_list($sv, $si, $checkf, $min_idx)
 {
     $ts = array();
     foreach (preg_split('/\\s+/', $sv->req[$si->name]) as $t) {
         if ($t !== "" && $this->tagger->check($t, $checkf)) {
             list($tag, $idx) = TagInfo::split_index($t);
             if ($min_idx) {
                 $t = $tag . "#" . max($min_idx, (double) $idx);
             }
             $ts[$tag] = $t;
         } else {
             if ($t !== "") {
                 $sv->set_error($si->name, $si->short_description . ": " . $this->tagger->error_html);
             }
         }
     }
     return array_values($ts);
 }
예제 #4
0
 private function normalize($cj, $old_user)
 {
     // Errors prevent saving
     global $Conf, $Me, $Now;
     // Canonicalize keys
     foreach (array("preferredEmail" => "preferred_email", "institution" => "affiliation", "voicePhoneNumber" => "phone", "addressLine1" => "address", "zipCode" => "zip", "postal_code" => "zip") as $x => $y) {
         if (isset($cj->{$x}) && !isset($cj->{$y})) {
             $cj->{$y} = $cj->{$x};
         }
     }
     // Stringiness
     foreach (array("firstName", "lastName", "email", "preferred_email", "affiliation", "phone", "old_password", "new_password", "city", "state", "zip", "country") as $k) {
         if (isset($cj->{$k}) && !is_string($cj->{$k})) {
             $this->set_error($k, "Format error [{$k}]");
             unset($cj->{$k});
         }
     }
     // Email
     if (!get($cj, "email") && $old_user) {
         $cj->email = $old_user->email;
     } else {
         if (!get($cj, "email")) {
             $this->set_error("email", "Email is required.");
         } else {
             if (!isset($this->errf["email"]) && !validate_email($cj->email) && (!$old_user || $old_user->email !== $cj->email)) {
                 $this->set_error("email", "Invalid email address “" . htmlspecialchars($cj->email) . "”.");
             }
         }
     }
     // ID
     if (get($cj, "id") === "new") {
         if (get($cj, "email") && Contact::id_by_email($cj->email)) {
             $this->set_error("email", "Email address “" . htmlspecialchars($cj->email) . "” is already in use.");
             $this->errf["email_inuse"] = true;
         }
     } else {
         if (!get($cj, "id") && $old_user && $old_user->contactId) {
             $cj->id = $old_user->contactId;
         }
         if (get($cj, "id") && !is_int($cj->id)) {
             $this->set_error("id", "Format error [id]");
         }
         if ($old_user && get($cj, "email") && strtolower($old_user->email) !== strtolower($cj->email) && Contact::id_by_email($cj->email)) {
             $this->set_error("email", "Email address “" . htmlspecialchars($cj->email) . "” is already in use. You may want to <a href=\"" . hoturl("mergeaccounts") . "\">merge these accounts</a>.");
         }
     }
     // Contactdb information
     if ($old_user && !$old_user->contactId) {
         if (!isset($cj->firstName) && !isset($cj->lastName)) {
             $cj->firstName = $old_user->firstName;
             $cj->lastName = $old_user->lastName;
         }
         if (!isset($cj->affiliation)) {
             $cj->affiliation = $old_user->affiliation;
         }
         if (!isset($cj->collaborators)) {
             $cj->collaborators = $old_user->collaborators;
         }
     }
     // Preferred email
     if (get($cj, "preferred_email") && !isset($this->errf["preferred_email"]) && !validate_email($cj->preferred_email) && (!$old_user || $old_user->preferredEmail !== $cj->preferred_email)) {
         $this->set_error("preferred_email", "Invalid email address “" . htmlspecialchars($cj->preferred_email) . "”");
     }
     // Address
     $address = array();
     if (is_array(get($cj, "address"))) {
         $address = $cj->address;
     } else {
         if (is_string(get($cj, "address"))) {
             $address[] = $cj->address;
         } else {
             if (get($cj, "address")) {
                 $this->set_error("address", "Format error [address]");
             }
         }
         if (is_string(get($cj, "address2"))) {
             $address[] = $cj->address2;
         } else {
             if (is_string(get($cj, "addressLine2"))) {
                 $address[] = $cj->addressLine2;
             } else {
                 if (get($cj, "address2") || get($cj, "addressLine2")) {
                     $this->set_error("address2", "Format error [address2]");
                 }
             }
         }
     }
     foreach ($address as $a) {
         if (!is_string($a)) {
             $this->set_error("address", "Format error [address]");
         }
     }
     if (count($address)) {
         $cj->address = $address;
     }
     // Collaborators
     if (is_array(get($cj, "collaborators"))) {
         foreach ($cj->collaborators as $c) {
             if (!is_string($c)) {
                 $this->set_error("collaborators", "Format error [collaborators]");
             }
         }
     }
     if (is_array(get($cj, "collaborators")) && !isset($this->errf["collaborators"])) {
         $cj->collaborators = join("\n", $cj->collaborators);
     }
     if (get($cj, "collaborators") && !is_string($cj->collaborators) && !isset($this->errf["collaborators"])) {
         $this->set_error("collaborators", "Format error [collaborators]");
     }
     // Disabled
     if (isset($cj->disabled)) {
         if (($x = friendly_boolean($cj->disabled)) !== null) {
             $cj->disabled = $x;
         } else {
             $this->set_error("disabled", "Format error [disabled]");
         }
     }
     // Follow
     if (isset($cj->follow)) {
         $cj->follow = $this->make_keyed_object($cj->follow, "follow");
         $cj->bad_follow = array();
         foreach ((array) $cj->follow as $k => $v) {
             if ($v && $k !== "reviews" && $k !== "allreviews" && $k !== "allfinal") {
                 $cj->bad_follow[] = $k;
             }
         }
     }
     // Roles
     if (isset($cj->roles)) {
         $cj->roles = $this->make_keyed_object($cj->roles, "roles");
         $cj->bad_roles = array();
         foreach ((array) $cj->roles as $k => $v) {
             if ($v && $k !== "pc" && $k !== "chair" && $k !== "sysadmin" && $k !== "no") {
                 $cj->bad_roles[] = $k;
             }
         }
         if ($this->no_deprivilege_self && $Me && $old_user && $old_user->contactId == $Me->contactId && Contact::parse_roles_json($cj->roles) < $Me->roles) {
             unset($cj->roles);
             $this->set_warning("roles", "Ignoring request to drop your privileges.");
         }
     }
     // Tags
     if (isset($cj->tags)) {
         $cj->tags = $this->make_tags_array($cj->tags, "tags");
     }
     if (isset($cj->add_tags) || isset($cj->remove_tags)) {
         // collect old tags as map by base
         if (!isset($cj->tags) && $old_user) {
             $cj->tags = preg_split("/[\\s,]+/", $old_user->contactTags);
         } else {
             if (!isset($cj->tags)) {
                 $cj->tags = array();
             }
         }
         $old_tags = array();
         foreach ($cj->tags as $t) {
             if ($t !== "") {
                 list($tag, $index) = TagInfo::split_index($t);
                 $old_tags[$tag] = $index;
             }
         }
         // process removals, then additions
         foreach ($this->make_tags_array(get($cj, "remove_tags"), "remove_tags") as $t) {
             list($tag, $index) = TagInfo::split_index($t);
             if ($index === false || get($old_tags, $tag) == $index) {
                 unset($old_tags[$tag]);
             }
         }
         foreach ($this->make_tags_array($cj->add_tags, "add_tags") as $t) {
             list($tag, $index) = TagInfo::split_index($t);
             $old_tags[$tag] = $index;
         }
         // collect results
         $cj->tags = array();
         foreach ($old_tags as $tag => $index) {
             $cj->tags[] = $tag . "#" . (double) $index;
         }
     }
     // Topics
     if (isset($cj->topics)) {
         $topics = $this->make_keyed_object($cj->topics, "topics");
         $topic_map = $Conf->topic_map();
         $cj->topics = (object) array();
         $cj->bad_topics = array();
         foreach ((array) $topics as $k => $v) {
             if (get($topic_map, $k)) {
                 /* OK */
             } else {
                 if (($x = array_search($k, $topic_map, true)) !== false) {
                     $k = $x;
                 } else {
                     $cj->bad_topics[] = $k;
                     continue;
                 }
             }
             if ($v === "mlow" || $v === "medium-low") {
                 $v = -1;
             } else {
                 if ($v === true || $v === "mhigh" || $v === "medium-high") {
                     $v = 2;
                 } else {
                     if ($v === "low") {
                         $v = -2;
                     } else {
                         if ($v === "high") {
                             $v = 4;
                         } else {
                             if ($v === "medium" || $v === "none" || $v === false) {
                                 $v = 0;
                             } else {
                                 if (is_numeric($v)) {
                                     $v = (int) $v;
                                 } else {
                                     $this->set_error("topics", "Topic interest format error");
                                     continue;
                                 }
                             }
                         }
                     }
                 }
             }
             $k = (string) $k;
             $cj->topics->{$k} = $v;
         }
     }
 }
예제 #5
0
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));
    }
}
예제 #6
0
 function pc_members()
 {
     if ($this->_pc_members_cache === null) {
         $pc = $pca = array();
         $result = $this->q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where roles!=0 and (roles&" . Contact::ROLE_PCLIKE . ")!=0");
         $by_name_text = $by_first_text = [];
         $this->_pc_tags_cache = ["pc" => "pc"];
         while ($result && ($row = Contact::fetch($result, $this))) {
             $pca[$row->contactId] = $row;
             if ($row->roles & Contact::ROLE_PC) {
                 $pc[$row->contactId] = $row;
             }
             if ($row->firstName || $row->lastName) {
                 $name_text = Text::name_text($row);
                 if (isset($by_name_text[$name_text])) {
                     $row->nameAmbiguous = $by_name_text[$name_text]->nameAmbiguous = true;
                 }
                 $by_name_text[$name_text] = $row;
             }
             if ($row->firstName) {
                 if (isset($by_first_text[$row->firstName])) {
                     $row->firstNameAmbiguous = $by_first_text[$row->firstName]->firstNameAmbiguous = true;
                 }
                 $by_first_text[$row->firstName] = $row;
             }
             if ($row->contactTags) {
                 foreach (explode(" ", $row->contactTags) as $t) {
                     list($tag, $value) = TagInfo::split_index($t);
                     if ($tag) {
                         $this->_pc_tags_cache[strtolower($tag)] = $tag;
                     }
                 }
             }
         }
         Dbl::free($result);
         uasort($pc, "Contact::compare");
         $order = 0;
         foreach ($pc as $row) {
             $row->sort_position = $order;
             ++$order;
         }
         $this->_pc_members_cache = $pc;
         uasort($pca, "Contact::compare");
         $this->_pc_members_and_admins_cache = $pca;
         ksort($this->_pc_tags_cache);
     }
     return $this->_pc_members_cache;
 }