Exemple #1
0
function fix_this_comment($r, $num, $from, $messageid)
{
    global $db;
    global $alloc_from_addresses2;
    if ($r["commentEmailUIDORIG"] != $num) {
        unset($projectID);
        if ($r["commentMaster"] == "task" && $r["commentMasterID"]) {
            $q = prepare("select projectID from task where taskID = %d", $r["commentMasterID"]);
            $db->query($q);
            $task_row = $db->row();
            $projectID = $task_row["projectID"];
        }
        // Try figure out and populate the commentCreatedUser/commentCreatedUserClientContactID fields
        list($from_address, $from_name) = parse_email_address($from);
        $person = new person();
        $personID = $person->find_by_email($from_address);
        $personID or $personID = $person->find_by_name($from_name);
        $sql = array();
        $sql[] = prepare("commentEmailUID = '%s'", trim($num));
        if ($personID) {
            $sql[] = prepare("commentCreatedUser = %d", $personID);
            $sql[] = "commentCreatedUserClientContactID = NULL";
        } else {
            $sql[] = "commentCreatedUser = NULL";
            $cc = new clientContact();
            $clientContactID = $cc->find_by_email($from_address, $projectID);
            $clientContactID or $clientContactID = $cc->find_by_name($from_name, $projectID);
            $clientContactID and $sql[] = prepare("commentCreatedUserClientContactID = %d", $clientContactID);
        }
        $sql[] = prepare("commentCreatedUserText = '%s'", trim($from));
        $sql[] = prepare("commentEmailMessageID = '%s'", trim($messageid));
        if (!in_array($from_address, $alloc_from_addresses2)) {
            // don't update items that are from alloc
            $q = prepare("UPDATE comment SET " . implode(",", $sql) . " WHERE commentID = %d", $r["commentID"]);
            $db->query($q);
            printorlog("FIXED: " . $q . " (old uid: " . $r["commentEmailUIDORIG"] . ")", "blue");
        }
    } else {
        // Try figure out and populate the commentCreatedUser/commentCreatedUserClientContactID fields
        list($from_address, $from_name) = parse_email_address($from);
        if (!in_array($from_address, $alloc_from_addresses2)) {
            // don't update items that are from alloc
            $sql = array();
            $sql[] = prepare("commentEmailUID = '%s'", trim($num));
            $sql[] = prepare("commentEmailMessageID = '%s'", trim($messageid));
            $q = prepare("UPDATE comment SET " . implode(",", $sql) . " WHERE commentID = %d", $r["commentID"]);
            $db->query($q);
            printorlog("GOOD: " . $q, "green");
        }
    }
}
Exemple #2
0
 function delete()
 {
     // delete all contacts and comments linked with this client as well
     $db = new db_alloc();
     $query = prepare("SELECT * FROM clientContact WHERE clientID=%d", $this->get_id());
     $db->query($query);
     while ($db->next_record()) {
         $clientContact = new clientContact();
         $clientContact->read_db_record($db);
         $clientContact->delete();
     }
     $query = prepare("SELECT * FROM comment WHERE commentType = 'client' and commentLinkID=%d", $this->get_id());
     $db->query($query);
     while ($db->next_record()) {
         $comment = new comment();
         $comment->read_db_record($db);
         $comment->delete();
     }
     return parent::delete();
 }
Exemple #3
0
function show_client_contacts()
{
    global $TPL;
    global $clientID;
    $TPL["clientContact_clientID"] = $clientID;
    if ($_POST["clientContact_delete"] && $_POST["clientContactID"]) {
        $clientContact = new clientContact();
        $clientContact->set_id($_POST["clientContactID"]);
        $clientContact->delete();
    }
    $client = new client();
    $client->set_id($clientID);
    $client->select();
    // other contacts
    $query = prepare("SELECT * \n                        FROM clientContact\n                       WHERE clientID=%d    \n                    ORDER BY clientContactActive DESC, primaryContact DESC, clientContactName", $clientID);
    $db = new db_alloc();
    $db->query($query);
    while ($db->next_record()) {
        $clientContact = new clientContact();
        $clientContact->read_db_record($db);
        if ($_POST["clientContact_edit"] && $_POST["clientContactID"] == $clientContact->get_id()) {
            continue;
        }
        $pc = "";
        if ($clientContact->get_value("primaryContact")) {
            $pc = " [Primary]";
        }
        $vcard_img = "icon_vcard.png";
        $clientContact->get_value("clientContactActive") or $vcard_img = "icon_vcard_faded.png";
        $vcard = '<a href="' . $TPL["url_alloc_client"] . 'clientContactID=' . $clientContact->get_id() . '&get_vcard=1"><img style="vertical-align:middle; padding:3px 6px 3px 3px;border: none" src="' . $TPL["url_alloc_images"] . $vcard_img . '" alt="Download VCard" ></a>';
        $col1 = array();
        $clientContact->get_value('clientContactName') and $col1[] = "<h2 style='margin:0px; display:inline;'>" . $vcard . $clientContact->get_value('clientContactName', DST_HTML_DISPLAY) . "</h2>" . $pc;
        $clientContact->get_value('clientContactStreetAddress') and $col1[] = $clientContact->get_value('clientContactStreetAddress', DST_HTML_DISPLAY);
        $clientContact->get_value('clientContactSuburb') || $clientContact->get_value('clientContactState') || $clientContact->get_value('clientContactPostcode') and $col1[] = $clientContact->get_value('clientContactSuburb', DST_HTML_DISPLAY) . ' ' . $clientContact->get_value('clientContactState', DST_HTML_DISPLAY) . " " . $clientContact->get_value('clientContactPostcode', DST_HTML_DISPLAY);
        $clientContact->get_value('clientContactCountry') and $col1[] = $clientContact->get_value('clientContactCountry', DST_HTML_DISPLAY);
        // find some gpl icons!
        #$ico_e = "<img src=\"".$TPL["url_alloc_images"]."/icon_email.gif\">";
        #$ico_p = "<img src=\"".$TPL["url_alloc_images"]."/icon_phone.gif\">";
        #$ico_m = "<img src=\"".$TPL["url_alloc_images"]."/icon_mobile.gif\">";
        #$ico_f = "<img src=\"".$TPL["url_alloc_images"]."/icon_fax.gif\">";
        $ico_e = "E: ";
        $ico_p = "P: ";
        $ico_m = "M: ";
        $ico_f = "F: ";
        $col2 = array();
        $email = $clientContact->get_value("clientContactEmail", DST_HTML_DISPLAY);
        $email = str_replace("<", "", $email);
        $email = str_replace(">", "", $email);
        $email = str_replace("&lt;", "", $email);
        $email = str_replace("&gt;", "", $email);
        $userName = $clientContact->get_value('clientContactName', DST_HTML_DISPLAY);
        if ($userName) {
            $mailto = '"' . $userName . '" <' . $email . ">";
        } else {
            $mailto = $email;
        }
        $email and $col2[] = $ico_e . "<a href='mailto:" . rawurlencode($mailto) . "'>" . $email . "</a>";
        $phone = $clientContact->get_value('clientContactPhone', DST_HTML_DISPLAY);
        $phone and $col2[] = $ico_p . $phone;
        $mobile = $clientContact->get_value('clientContactMobile', DST_HTML_DISPLAY);
        $mobile and $col2[] = $ico_m . $mobile;
        $fax = $clientContact->get_value('clientContactFax', DST_HTML_DISPLAY);
        $fax and $col2[] = $ico_f . $fax;
        if ($clientContact->get_value("clientContactActive")) {
            $class_extra = " loud";
        } else {
            $class_extra = " quiet";
        }
        $buttons = '<nobr>
      <button type="submit" name="clientContact_delete" value="1" class="delete_button">Delete<i class="icon-trash"></i></button>
      <button type="submit" name="clientContact_edit" value="1"">Edit<i class="icon-edit"></i></button>
      </nobr>';
        $rtn[] = '<form action="' . $TPL["url_alloc_client"] . '" method="post">';
        $rtn[] = '<input type="hidden" name="clientContactID" value="' . $clientContact->get_id() . '">';
        $rtn[] = '<input type="hidden" name="clientID" value="' . $clientID . '">';
        $rtn[] = '<div class="panel' . $class_extra . ' corner">';
        $rtn[] = '<table width="100%" cellspacing="0" border="0">';
        $rtn[] = '<tr>';
        $rtn[] = '  <td width="25%" valign="top"><span class="nobr">' . implode('</span><br><span class="nobr">', $col1) . '</span>&nbsp;</td>';
        $rtn[] = '  <td width="20%" valign="top"><span class="nobr">' . implode('</span><br><span class="nobr">', $col2) . '</span>&nbsp;</td>';
        $rtn[] = '  <td width="50%" align="left" valign="top">' . nl2br($clientContact->get_value('clientContactOther', DST_HTML_DISPLAY)) . '&nbsp;</td>';
        $rtn[] = '  <td align="right" class="right nobr">' . $buttons . '</td>';
        $rtn[] = '  <td align="right" class="right nobr" width="1%">' . page::star("clientContact", $clientContact->get_id()) . '</td>';
        $rtn[] = '</tr>';
        $rtn[] = '</table>';
        $rtn[] = '</div>';
        $rtn[] = '<input type="hidden" name="sessID" value="' . $TPL["sessID"] . '">';
        $rtn[] = '</form>';
    }
    if (is_array($rtn)) {
        $TPL["clientContacts"] = implode("\n", $rtn);
    }
    if ($_POST["clientContact_edit"] && $_POST["clientContactID"]) {
        $clientContact = new clientContact();
        $clientContact->set_id($_POST["clientContactID"]);
        $clientContact->select();
        $clientContact->set_values("clientContact_");
        if ($clientContact->get_value("primaryContact")) {
            $TPL["primaryContact_checked"] = " checked";
        }
        if ($clientContact->get_value("clientContactActive")) {
            $TPL["clientContactActive_checked"] = " checked";
        }
    } else {
        if ($rtn) {
            $TPL["class_new_client_contact"] = "hidden";
        }
    }
    if (!$_POST["clientContactID"] || $_POST["clientContact_save"]) {
        $TPL["clientContactActive_checked"] = " checked";
    }
    include_template("templates/clientContactM.tpl");
}
Exemple #4
0
 function find_email($debug = false, $get_blobs = false, $ignore_date = false)
 {
     $info = inbox::get_mail_info();
     $mailbox = $this->get_value("commentMaster") . $this->get_value("commentMasterID");
     $mail = new email_receive($info);
     $mail->open_mailbox(config::get_config_item("allocEmailFolder") . "/" . $mailbox, OP_HALFOPEN + OP_READONLY);
     $mail->check_mail();
     $msg_nums = $mail->get_all_email_msg_uids();
     $debug and print "<hr><br><b>find_email(): " . date("Y-m-d H:i:s") . " found " . count($msg_nums) . " emails for mailbox: " . $mailbox . "</b>";
     // fetch and parse email
     foreach ((array) $msg_nums as $num) {
         $debug and print "<hr><br>Examining message number: " . $num;
         unset($mimebits);
         // this will stream output
         $mail->set_msg($num);
         $mail->get_msg_header();
         $text = $mail->fetch_mail_text();
         list($from1, $e1n) = parse_email_address($mail->mail_headers["from"]);
         list($from2, $e2n) = parse_email_address($this->get_value("commentCreatedUserText"));
         if (!$from2 && $this->get_value("commentCreatedUser")) {
             $p = new person();
             $p->set_id($this->get_value("commentCreatedUser"));
             $p->select();
             $from2 = $p->get_value("emailAddress");
         }
         if (!$from2 && $this->get_value("commentCreatedUserClientContactID")) {
             $p = new clientContact();
             $p->set_id($this->get_value("commentCreatedUserClientContactID"));
             $p->select();
             $from2 = $p->get_value("clientContactEmail");
         }
         $text1 = str_replace(array("\\s", "\n", "\r"), "", trim($text));
         $text2 = str_replace(array("\\s", "\n", "\r"), "", trim($this->get_value("comment")));
         $date = format_date("U", $this->get_value("commentCreatedTime"));
         $date1 = strtotime($mail->mail_headers["date"]) - 300;
         $date3 = strtotime($mail->mail_headers["date"]) + 300;
         similar_text($text1, $text2, $percent);
         if ($percent >= 99 && ($from1 == $from2 || !$from2 || same_email_address($from1, config::get_config_item("AllocFromEmailAddress"))) && ($date > $date1 && $date < $date3 || $ignore_date)) {
             $debug and print "<br><b style='color:green'>Found you! Msg no: " . $num . " in mailbox: " . $mailbox . " for commentID: " . $this->get_id() . "</b>";
             foreach ((array) $mail->mail_parts as $v) {
                 $s = $v["part_object"];
                 // structure
                 $raw_data = imap_fetchbody($mail->connection, $mail->msg_uid, $v["part_number"], FT_UID | FT_PEEK);
                 $thing = $mail->decode_part($s->encoding, $raw_data);
                 $filename = $mail->get_parameter_attribute_value($s->parameters, "name");
                 $filename or $filename = $mail->get_parameter_attribute_value($s->parameters, "filename");
                 $filename or $filename = $mail->get_parameter_attribute_value($s->dparameters, "name");
                 $filename or $filename = $mail->get_parameter_attribute_value($s->dparameters, "filename");
                 $bits = array();
                 $bits["part"] = $v["part_number"];
                 $bits["name"] = $filename;
                 $bits["size"] = strlen($thing);
                 $get_blobs and $bits["blob"] = $thing;
                 $filename and $mimebits[] = $bits;
             }
             $mail->close();
             return array($mail, $text, $mimebits);
         } else {
             similar_text($text1, $text2, $percent);
             $debug and print "<br>TEXT: " . sprintf("%d", $text1 == $text2) . " (" . sprintf("%d", $percent) . "%)";
             #$debug and print "<br>Text1:<br>".$text1."<br>* * *<br>";
             #$debug and print "Text2:<br>".$text2."<br>+ + +</br>";
             $debug and print "<br>FROM: " . sprintf("%d", $from1 == $from2 || !$from2 || same_email_address($from1, config::get_config_item("AllocFromEmailAddress")));
             $debug and print " From1: " . page::htmlentities($from1);
             $debug and print " From2: " . page::htmlentities($from2);
             $debug and print "<br>DATE: " . sprintf("%d", $date > $date1 && $date < $date3) . " (" . date("Y-m-d H:i:s", $date) . " | " . date("Y-m-d H:i:s", $date1) . " | " . date("Y-m-d H:i:s", $date3) . ")";
             $debug and print "<br>";
         }
     }
     $mail->close();
     return array(false, false, false);
 }
 function expand_ip($ip, $projectID = null)
 {
     // jon               alloc username
     // jon@jon.com       alloc username or client or stranger
     // Jon <*****@*****.**> alloc username or client or stranger
     // Jon Smith         alloc fullname or client fullname
     // username
     $people or $people = person::get_people_by_username();
     if (preg_match("/^\\w+\$/i", $ip)) {
         return array($people[$ip]["personID"], $people[$ip]["name"], $people[$ip]["emailAddress"]);
     }
     // email address
     $people = person::get_people_by_username("emailAddress");
     list($email, $name) = parse_email_address($ip);
     if ($people[$email]) {
         return array($people[$email]["personID"], $people[$email]["name"], $people[$email]["emailAddress"]);
     }
     // Jon smith
     if (preg_match("/^[\\w\\s]+\$/i", $ip)) {
         $personID = person::find_by_name($ip, 100);
         if ($personID) {
             $people = person::get_people_by_username("personID");
             return array($personID, $people[$personID]["name"], $people[$personID]["emailAddress"]);
         }
         $ccid = clientContact::find_by_name($ip, $projectID, 100);
         if ($ccid) {
             $cc = new clientContact();
             $cc->set_id($ccid);
             $cc->select();
             $name = $cc->get_value("clientContactName");
             $email = $cc->get_value("clientContactEmail");
         }
     }
     return array(null, $name, $email);
 }
Exemple #6
0
    $TPL["task_pendingTaskIDs"] = $row["pendingTaskIDs"];
    $TPL["task_tags"] = implode(", ", $task->get_tags());
} else {
    $TPL["taskSelfLink"] = "New Task";
    $TPL["main_alloc_title"] = "New Task - " . APPLICATION_NAME;
}
$TPL["tagOptions"] = page::select_options($task->get_tags(true), $task->get_tags(), 300);
if (!$task->get_id()) {
    $TPL["message_help"][] = "Enter a Task Name and click the Save button to create a new Task.";
    $TPL["task_dateTargetStart"] or $TPL["task_dateTargetStart"] = date("Y-m-d");
}
$TPL["task"] = $task;
// Printer friendly view
if ($_GET["media"] == "print") {
    if (has("client")) {
        $client = new client();
        $client->set_id($project->get_value("clientID"));
        $client->select();
        $client->set_values("client_");
    }
    if (has("project") && has("client")) {
        $project = $task->get_foreign_object("project");
        $clientContact = new clientContact();
        $clientContact->set_id($project->get_value("clientContactID"));
        $clientContact->select();
        $clientContact->set_values("clientContact_");
    }
    include_template("templates/taskPrinterM.tpl");
} else {
    include_template("templates/taskM.tpl");
}
 public static function get_list($_FORM)
 {
     global $TPL;
     $filter = clientContact::get_list_filter($_FORM);
     if (is_array($filter) && count($filter)) {
         $filter = " WHERE " . implode(" AND ", $filter);
     }
     $q = "SELECT clientContact.*, client.*\n            FROM clientContact\n       LEFT JOIN client ON client.clientID = clientContact.clientID\n                 " . $filter . " \n        GROUP BY clientContact.clientContactID \n        ORDER BY clientContactName,clientContact.primaryContact asc";
     $db = new db_alloc();
     $db->query($q);
     while ($row = $db->next_record()) {
         $c = new client();
         $c->read_db_record($db);
         $row["clientLink"] = $c->get_client_link($_FORM);
         $row["clientContactEmail"] and $row["clientContactEmail"] = "<a href=\"mailto:" . page::htmlentities($row["clientContactName"] . " <" . $row["clientContactEmail"] . ">") . "\">" . page::htmlentities($row["clientContactEmail"]) . "</a>";
         $rows[] = $row;
     }
     return $rows;
 }
Exemple #8
0
$client->set_tpl_values("client_");
// If a client has been chosen
if ($clientID) {
    $query = prepare("SELECT * \n                      FROM clientContact\n                     WHERE clientContact.clientID = %d AND clientContact.primaryContact = true", $clientID);
    $db->query($query);
    $cc = new clientContact();
    $cc->read_db_record($db);
    $one = $client->format_address("postal");
    $two = $client->format_address("street");
    $thr = $cc->format_contact();
    $fou = $project->format_client_old();
    $temp = str_replace("<br>", "", $fou);
    $temp and $thr = $fou;
    $url = $TPL["url_alloc_client"] . "clientID=" . $clientID;
    if ($project->get_value("clientContactID")) {
        $cc = new clientContact();
        $cc->set_id($project->get_value("clientContactID"));
        $cc->select();
        $fiv = $cc->format_contact();
        $temp = str_replace("<br>", "", $fiv);
        $temp and $thr = $fiv;
    }
    $TPL["clientDetails"] = "<table width=\"100%\">";
    $TPL["clientDetails"] .= "<tr>";
    $TPL["clientDetails"] .= "<td colspan=\"3\"><h2 style=\"margin-bottom:0px; display:inline;\"><a href=" . $url . ">" . $TPL["client_clientName"] . "</a></h2></td>    ";
    $TPL["clientDetails"] .= "</tr>";
    $TPL["clientDetails"] .= "<tr>";
    $one and $TPL["clientDetails"] .= "<td class=\"nobr\"><u>Postal Address</u></td>";
    $two and $TPL["clientDetails"] .= "<td class=\"nobr\"><u>Street Address</u></td>";
    $thr and $TPL["clientDetails"] .= "<td><u>Contact</u></td>";
    $TPL["clientDetails"] .= "</tr>";
Exemple #9
0
     $client->set_value("clientStatus", "current");
     $client->set_value("clientModifiedUser", $current_user->get_id());
     $client->save();
     if ($client->get_id()) {
         if (rtrim($data[9])) {
             $comment = new comment();
             $comment->set_value("commentMaster", "client");
             $comment->set_value("commentMasterID", $client->get_id());
             $comment->set_value("commentType", "client");
             $comment->set_value("commentLinkID", $client->get_id());
             $comment->set_value("comment", $data[9]);
             $comment->save();
             $comment_id = $comment->get_id();
         }
         if ($data[10] || $data[11]) {
             $cc = new clientContact();
             $cc->set_value("clientID", $client->get_id());
             $cc->set_value("primaryContact", 1);
             $cc->set_value("clientContactName", $data[10]);
             $cc->set_value("clientContactEmail", $data[11]);
             $cc->save();
             $cc_id = $cc->get_id();
         }
     }
     $x++;
     echo "<br>" . $client->get_id() . " --- " . $cc_id . " --- " . $comment_id;
     if ($x > 4) {
         //die();
     }
 }
 fclose($handle);
Exemple #10
0
 /**
  * Convert a comma separated string of names, into an array with email addresses
  * @param string $people
  * @param string $entity the related entity that can assist in the look up
  * @param integer $entityID the id of the related entity
  * @return array an array of people, indexed by their email address
  */
 public function get_people($options = array(), $entity = "", $entityID = "")
 {
     $person_table =& get_cached_table("person");
     $people = $options;
     if ($entity && $entityID) {
         $e = new $entity();
         $e->set_id($entityID);
         $e->select();
         in_array("default", $people) and $default_recipients = $e->get_all_parties();
         in_array("internal", $people) and $internal_recipients = $e->get_all_parties();
     }
     // remove default and internal from the array
     $clean_people = array_diff($people, array("default", "internal"));
     if (is_object($e)) {
         $projectID = $e->get_project_id();
         $p = new project();
         $p->set_id($projectID);
         $p->select();
         $client = $p->get_foreign_object("client");
         $clientID = $client->get_id();
     }
     foreach ((array) $default_recipients as $email => $info) {
         if ($info["selected"]) {
             $rtn[$email] = $this->reduce_person_info($info);
         }
     }
     foreach ((array) $internal_recipients as $email => $info) {
         if ($info["selected"] && !$info["external"]) {
             $rtn[$email] = $this->reduce_person_info($info);
         }
     }
     foreach ((array) $clean_people as $person) {
         $bad_person = true;
         $person = trim($person);
         // personID
         if (is_numeric($person)) {
             if ($person_table[$person]["personActive"]) {
                 $rtn[$person_table[$person]["emailAddress"]] = $person_table[$person];
                 $bad_person = false;
                 continue;
             }
             // email addresses
         } else {
             if (in_str("@", $person)) {
                 foreach ($person_table as $pid => $data) {
                     if (same_email_address($person, $data["emailAddress"]) && $data["personActive"]) {
                         $rtn[$data["emailAddress"]] = $data;
                         $bad_person = false;
                         continue 2;
                     }
                 }
                 if ($ccID = clientContact::find_by_email($person)) {
                     $cc = new clientContact();
                     $cc->set_id($ccID);
                     $cc->select();
                     $rtn[$cc->get_value("clientContactEmail")] = $cc->row();
                     $bad_person = false;
                     continue;
                 }
                 // If we get here, then return the email address entered
                 list($e, $n) = parse_email_address($person);
                 $rtn[$e] = array("emailAddress" => $e, "name" => $n);
                 $bad_person = false;
                 continue;
                 // usernames, partial and full names
             } else {
                 foreach ($person_table as $pid => $data) {
                     // If matches username
                     if (strtolower($person) == strtolower($data["username"]) && $data["personActive"]) {
                         $rtn[$data["emailAddress"]] = $data;
                         $bad_person = false;
                         continue 2;
                     }
                 }
                 foreach ($person_table as $pid => $data) {
                     // If matches name
                     if (strtolower($person) == strtolower($data["firstName"] . " " . $data["surname"]) && $data["personActive"]) {
                         $rtn[$data["emailAddress"]] = $data;
                         $bad_person = false;
                         continue 2;
                     }
                 }
                 foreach ($person_table as $pid => $data) {
                     // If matches a section of name, eg: a search for "Ale" will match the full name "Alex Lance"
                     if (strtolower($person) == strtolower(substr(strtolower($data["firstName"] . " " . $data["surname"]), 0, strlen($person))) && $data["personActive"]) {
                         $rtn[$data["emailAddress"]] = $data;
                         $bad_person = false;
                         continue 2;
                     }
                 }
                 if ($ccID = clientContact::find_by_nick($person, $clientID)) {
                     $cc = new clientContact();
                     $cc->set_id($ccID);
                     $cc->select();
                     $rtn[$cc->get_value("clientContactEmail")] = $cc->row();
                     $bad_person = false;
                     continue;
                 }
                 if ($ccID = clientContact::find_by_name($person, $projectID)) {
                     $cc = new clientContact();
                     $cc->set_id($ccID);
                     $cc->select();
                     $rtn[$cc->get_value("clientContactEmail")] = $cc->row();
                     $bad_person = false;
                     continue;
                 }
                 if ($ccID = clientContact::find_by_partial_name($person, $projectID)) {
                     $cc = new clientContact();
                     $cc->set_id($ccID);
                     $cc->select();
                     $rtn[$cc->get_value("clientContactEmail")] = $cc->row();
                     $bad_person = false;
                     continue;
                 }
             }
         }
         if ($bad_person) {
             die("Unable to find person: " . $person);
         }
     }
     foreach ((array) $rtn as $id => $p) {
         $rtn[$id] = $this->reduce_person_info($p);
     }
     return (array) $rtn;
 }