/**
* TODO: merge use of $options and $email arrays to just $email
*
* @param int $issue_id
* @param string $type type of email
* @param string $from
* @param string $to
* @param string $cc
* @param string $subject
* @param string $body
* @param array $options optional parameters
* - (int) parent_sup_id
* - (array) iaf_ids attachment file ids
* - (bool) add_unknown
* - (int) ema_id
* @return int 1 if it worked, -1 otherwise
*/
public static function sendEmail($issue_id, $type, $from, $to, $cc, $subject, $body, $options = array())
{
$parent_sup_id = $options['parent_sup_id'];
$iaf_ids = $options['iaf_ids'];
$add_unknown = $options['add_unknown'];
$ema_id = $options['ema_id'];
$current_usr_id = Auth::getUserID();
$prj_id = Issue::getProjectID($issue_id);
// if we are replying to an existing email, set the In-Reply-To: header accordingly
$in_reply_to = $parent_sup_id ? self::getMessageIDByID($parent_sup_id) : false;
// get ID of whoever is sending this.
$sender_usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($from)) ?: false;
// remove extra 'Re: ' from subject
$subject = Mail_Helper::removeExcessRe($subject, true);
$internal_only = false;
$message_id = Mail_Helper::generateMessageID();
// process any files being uploaded
// from ajax upload, attachment file ids
if ($iaf_ids) {
// FIXME: is it correct to use sender from post data?
$attach_usr_id = $sender_usr_id ?: $current_usr_id;
Attachment::attachFiles($issue_id, $attach_usr_id, $iaf_ids, false, 'Attachment originated from outgoing email');
}
// hack needed to get the full headers of this web-based email
$full_email = self::buildFullHeaders($issue_id, $message_id, $from, $to, $cc, $subject, $body, $in_reply_to, $iaf_ids);
// email blocking should only be done if this is an email about an associated issue
if ($issue_id) {
$user_info = User::getNameEmail($current_usr_id);
// check whether the current user is allowed to send this email to customers or not
if (!self::isAllowedToEmail($issue_id, $user_info['usr_email'])) {
// add the message body as a note
$note = Mail_Helper::getCannedBlockedMsgExplanation() . $body;
$note_options = array('full_message' => $full_email, 'is_blocked' => true);
Note::insertNote($current_usr_id, $issue_id, $subject, $note, $note_options);
$email_details = array('from' => $from, 'to' => $to, 'cc' => $cc, 'subject' => $subject, 'body' => &$body, 'message' => &$body, 'title' => $subject);
Workflow::handleBlockedEmail($prj_id, $issue_id, $email_details, 'web');
return 1;
}
}
// only send a direct email if the user doesn't want to add the Cc'ed people to the notification list
if (($add_unknown || Workflow::shouldAutoAddToNotificationList($prj_id)) && $issue_id) {
// add the recipients to the notification list of the associated issue
$recipients = array($to);
$recipients = array_merge($recipients, self::getRecipientsCC($cc));
foreach ($recipients as $address) {
if ($address && !Notification::isIssueRoutingSender($issue_id, $address)) {
$actions = Notification::getDefaultActions($issue_id, $address, 'add_unknown_user');
Notification::subscribeEmail($current_usr_id, $issue_id, Mail_Helper::getEmailAddress($address), $actions);
}
}
} else {
// Usually when sending out emails associated to an issue, we would
// simply insert the email in the table and call the Notification::notifyNewEmail() method,
// but on this case we need to actually send the email to the recipients that are not
// already in the notification list for the associated issue, if any.
// In the case of replying to an email that is not yet associated with an issue, then
// we are always directly sending the email, without using any notification list
// functionality.
if ($issue_id) {
// send direct emails only to the unknown addresses, and leave the rest to be
// catched by the notification list
$from = Notification::getFixedFromHeader($issue_id, $from, 'issue');
// build the list of unknown recipients
if ($to) {
$recipients = array($to);
$recipients = array_merge($recipients, self::getRecipientsCC($cc));
} else {
$recipients = self::getRecipientsCC($cc);
}
$unknowns = array();
foreach ($recipients as $address) {
if (!Notification::isSubscribedToEmails($issue_id, $address)) {
$unknowns[] = $address;
}
}
if ($unknowns) {
$to2 = array_shift($unknowns);
$cc2 = implode('; ', $unknowns);
// send direct emails
self::sendDirectEmail($issue_id, $from, $to2, $cc2, $subject, $body, $_FILES['attachment'], $message_id, $sender_usr_id);
}
} else {
// send direct emails to all recipients, since we don't have an associated issue
$project_info = Project::getOutgoingSenderAddress(Auth::getCurrentProject());
// use the project-related outgoing email address, if there is one
if (!empty($project_info['email'])) {
$from = Mail_Helper::getFormattedName(User::getFullName($current_usr_id), $project_info['email']);
} else {
// otherwise, use the real email address for the current user
$from = User::getFromHeader($current_usr_id);
}
// send direct emails
self::sendDirectEmail($issue_id, $from, $to, $cc, $subject, $body, $_FILES['attachment'], $message_id);
}
}
$email = array('customer_id' => 'NULL', 'issue_id' => $issue_id, 'ema_id' => $ema_id, 'message_id' => $message_id, 'date' => Date_Helper::getCurrentDateGMT(), 'from' => $from, 'to' => $to, 'cc' => $cc, 'subject' => $subject, 'body' => $body, 'full_email' => $full_email);
// associate this new email with a customer, if appropriate
if (Auth::getCurrentRole() == User::getRoleID('Customer')) {
if ($issue_id) {
$crm = CRM::getInstance($prj_id);
try {
$contact = $crm->getContact(User::getCustomerContactID($current_usr_id));
$issue_contract = $crm->getContract(Issue::getContractID($issue_id));
if ($contact->canAccessContract($issue_contract)) {
$email['customer_id'] = $issue_contract->getCustomerID();
}
} catch (CRMException $e) {
}
} else {
$customer_id = User::getCustomerID($current_usr_id);
if ($customer_id && $customer_id != -1) {
$email['customer_id'] = $customer_id;
}
}
}
$email['has_attachment'] = $iaf_ids ? 1 : 0;
$structure = Mime_Helper::decode($full_email, true, false);
$email['headers'] = $structure->headers;
self::insertEmail($email, $structure, $sup_id);
if ($issue_id) {
// need to send a notification
Notification::notifyNewEmail($current_usr_id, $issue_id, $email, $internal_only, false, $type, $sup_id);
// mark this issue as updated
$has_customer = $email['customer_id'] && $email['customer_id'] != 'NULL';
if ($has_customer && (!$current_usr_id || User::getRoleByUser($current_usr_id, $prj_id) == User::getRoleID('Customer'))) {
Issue::markAsUpdated($issue_id, 'customer action');
} else {
if ($sender_usr_id && User::getRoleByUser($sender_usr_id, $prj_id) > User::getRoleID('Customer')) {
Issue::markAsUpdated($issue_id, 'staff response');
} else {
Issue::markAsUpdated($issue_id, 'user response');
}
}
History::add($issue_id, $current_usr_id, 'email_sent', 'Outgoing email sent by {user}', array('user' => User::getFullName($current_usr_id)));
}
return 1;
}
}
$customer_id = Issue::getCustomerID($HTTP_GET_VARS['issue']);
if (!empty($customer_id)) {
$contact_emails = array_keys(Customer::getContactEmailAssocList($prj_id, $customer_id));
$unknown_contacts = array();
foreach ($sender_emails as $email => $address) {
if (!@in_array($email, $contact_emails)) {
$usr_id = User::getUserIDByEmail($email);
if (empty($usr_id)) {
$unknown_contacts[] = $address;
} else {
// if we got a real user ID, check if the customer user is the correct one
// (i.e. a contact from the customer associated with the selected issue)
if (User::getRoleByUser($usr_id, $prj_id) == User::getRoleID('Customer')) {
// also check if the associated customer ID, if any, matches the one in the issue
$user_customer_id = User::getCustomerID($usr_id);
if ($user_customer_id != $customer_id) {
$unknown_contacts[] = $address;
}
}
}
}
}
if (count($unknown_contacts) > 0) {
$tpl->assign('unknown_contacts', $unknown_contacts);
}
}
}
}
$tpl->assign("current_user_prefs", Prefs::get(Auth::getUserID()));
$tpl->displayTemplate();
Auth::checkAuthentication(APP_COOKIE, 'index.php?err=5', true);
$usr_id = Auth::getUserID();
$prj_id = Auth::getCurrentProject();
if (!Customer::hasCustomerIntegration($prj_id)) {
// show all FAQ entries
$support_level_id = -1;
} else {
if (!Customer::doesBackendUseSupportLevels($prj_id)) {
// show all FAQ entries
$support_level_id = -1;
} else {
if (Auth::getCurrentRole() != User::getRoleID('Customer')) {
// show all FAQ entries
$support_level_id = -1;
} else {
$customer_id = User::getCustomerID(Auth::getUserID());
$support_level_id = Customer::getSupportLevelID($prj_id, $customer_id);
}
}
}
$tpl->assign("faqs", FAQ::getListBySupportLevel($support_level_id));
if (!empty($HTTP_GET_VARS["id"])) {
$t = FAQ::getDetails($HTTP_GET_VARS['id']);
// check if this customer should have access to this FAQ entry or not
if ($support_level_id != -1 && !in_array($support_level_id, $t['support_levels'])) {
$tpl->assign('faq', -1);
} else {
$t['faq_created_date'] = Date_API::getFormattedDate($t["faq_created_date"]);
$tpl->assign("faq", $t);
}
}
/**
* Method used to check for the appropriate authentication for a specific
* page. It will check for the cookie name provided and redirect the user
* to another page if needed.
*
* @access public
* @param string $cookie_name The name of the cookie to check for
* @param string $failed_url The URL to redirect to if the user is not authenticated
* @param boolean $is_popup Flag to tell the function if the current page is a popup window or not
* @return void
*/
function checkAuthentication($cookie_name, $failed_url = NULL, $is_popup = false)
{
global $HTTP_COOKIE_VARS;
if ($failed_url == NULL) {
$failed_url = APP_RELATIVE_URL . "index.php?err=5";
}
$failed_url .= "&url=" . Auth::getRequestedURL();
if (!isset($HTTP_COOKIE_VARS[$cookie_name])) {
Auth::redirect($failed_url, $is_popup);
}
$cookie = $HTTP_COOKIE_VARS[$cookie_name];
$cookie = unserialize(base64_decode($cookie));
if (!Auth::isValidCookie($cookie)) {
Auth::removeCookie($cookie_name);
Auth::redirect($failed_url, $is_popup);
}
if (Auth::isPendingUser($cookie["email"])) {
Auth::removeCookie($cookie_name);
Auth::redirect(APP_RELATIVE_URL . "index.php?err=9", $is_popup);
}
if (!Auth::isActiveUser($cookie["email"])) {
Auth::removeCookie($cookie_name);
Auth::redirect(APP_RELATIVE_URL . "index.php?err=7", $is_popup);
}
// check whether the project selection is set or not
$prj_id = Auth::getCurrentProject();
if (empty($prj_id)) {
// redirect to select project page
Auth::redirect(APP_RELATIVE_URL . "select_project.php?url=" . Auth::getRequestedURL(), $is_popup);
}
// check the expiration date for a 'Customer' type user
$customer_id = User::getCustomerID(Auth::getUserID());
if (!empty($customer_id) && $customer_id != -1) {
$status = Customer::getContractStatus($prj_id, $customer_id);
if ($status == 'expired') {
Auth::removeCookie($cookie_name);
Auth::redirect(APP_RELATIVE_URL . "index.php?err=10&email=" . $cookie["email"], $is_popup);
}
}
// auto switch project
if (isset($_GET['switch_prj_id'])) {
Auth::setCurrentProject($_GET['switch_prj_id'], false);
Auth::redirect($_SERVER['PHP_SELF'] . '?' . str_replace("switch_prj_id=" . $_GET['switch_prj_id'], "", $_SERVER['QUERY_STRING']));
}
// if the current session is still valid, then renew the expiration
Auth::createLoginCookie($cookie_name, $cookie['email'], $cookie['autologin']);
// renew the project cookie as well
$prj_cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
Auth::setCurrentProject($prj_id, $prj_cookie["remember"]);
}
/**
* Method used to build the overall customer profile from the information
* stored in the customer database.
*
* @access public
* @param integer $usr_id The Eventum user ID
* @return array The customer profile information
*/
function getProfile($usr_id)
{
// this is used to return all details about the customer/contact in one fell swoop.
// for this example it will just return the details
return $this->getDetails(User::getCustomerID($usr_id));
}
/**
* Method used to send an email from the user interface.
*
* @access public
* @return integer 1 if it worked, -1 otherwise
*/
function sendEmail($parent_sup_id = FALSE)
{
global $HTTP_POST_VARS, $HTTP_SERVER_VARS;
// if we are replying to an existing email, set the In-Reply-To: header accordingly
if ($parent_sup_id) {
$in_reply_to = Support::getMessageIDByID($parent_sup_id);
} else {
$in_reply_to = false;
}
// get ID of whoever is sending this.
$sender_usr_id = User::getUserIDByEmail(Mail_API::getEmailAddress($HTTP_POST_VARS["from"]));
if (empty($sender_usr_id)) {
$sender_usr_id = false;
}
// get type of email this is
if (!empty($HTTP_POST_VARS['type'])) {
$type = $HTTP_POST_VARS['type'];
} else {
$type = '';
}
// remove extra 'Re: ' from subject
$HTTP_POST_VARS['subject'] = Mail_API::removeExcessRe($HTTP_POST_VARS['subject'], true);
$internal_only = false;
$message_id = Mail_API::generateMessageID();
// hack needed to get the full headers of this web-based email
$full_email = Support::buildFullHeaders($HTTP_POST_VARS["issue_id"], $message_id, $HTTP_POST_VARS["from"], $HTTP_POST_VARS["to"], $HTTP_POST_VARS["cc"], $HTTP_POST_VARS["subject"], $HTTP_POST_VARS["message"], $in_reply_to);
// email blocking should only be done if this is an email about an associated issue
if (!empty($HTTP_POST_VARS['issue_id'])) {
$user_info = User::getNameEmail(Auth::getUserID());
// check whether the current user is allowed to send this email to customers or not
if (!Support::isAllowedToEmail($HTTP_POST_VARS["issue_id"], $user_info['usr_email'])) {
// add the message body as a note
$HTTP_POST_VARS['blocked_msg'] = $full_email;
$HTTP_POST_VARS['title'] = $HTTP_POST_VARS["subject"];
$HTTP_POST_VARS['note'] = Mail_API::getCannedBlockedMsgExplanation() . $HTTP_POST_VARS["message"];
Note::insert(Auth::getUserID(), $HTTP_POST_VARS["issue_id"]);
Workflow::handleBlockedEmail(Issue::getProjectID($HTTP_POST_VARS['issue_id']), $HTTP_POST_VARS['issue_id'], $HTTP_POST_VARS, 'web');
return 1;
}
}
// only send a direct email if the user doesn't want to add the Cc'ed people to the notification list
if (@$HTTP_POST_VARS['add_unknown'] == 'yes') {
if (!empty($HTTP_POST_VARS['issue_id'])) {
// add the recipients to the notification list of the associated issue
$recipients = array($HTTP_POST_VARS['to']);
$recipients = array_merge($recipients, Support::getRecipientsCC($HTTP_POST_VARS['cc']));
for ($i = 0; $i < count($recipients); $i++) {
if (!empty($recipients[$i]) && !Notification::isIssueRoutingSender($HTTP_POST_VARS["issue_id"], $recipients[$i])) {
Notification::subscribeEmail(Auth::getUserID(), $HTTP_POST_VARS["issue_id"], Mail_API::getEmailAddress($recipients[$i]), array('emails'));
}
}
}
} else {
// Usually when sending out emails associated to an issue, we would
// simply insert the email in the table and call the Notification::notifyNewEmail() method,
// but on this case we need to actually send the email to the recipients that are not
// already in the notification list for the associated issue, if any.
// In the case of replying to an email that is not yet associated with an issue, then
// we are always directly sending the email, without using any notification list
// functionality.
if (!empty($HTTP_POST_VARS['issue_id'])) {
// send direct emails only to the unknown addresses, and leave the rest to be
// catched by the notification list
$from = Notification::getFixedFromHeader($HTTP_POST_VARS['issue_id'], $HTTP_POST_VARS['from'], 'issue');
// build the list of unknown recipients
if (!empty($HTTP_POST_VARS['to'])) {
$recipients = array($HTTP_POST_VARS['to']);
$recipients = array_merge($recipients, Support::getRecipientsCC($HTTP_POST_VARS['cc']));
} else {
$recipients = Support::getRecipientsCC($HTTP_POST_VARS['cc']);
}
$unknowns = array();
for ($i = 0; $i < count($recipients); $i++) {
if (!Notification::isSubscribedToEmails($HTTP_POST_VARS['issue_id'], $recipients[$i])) {
$unknowns[] = $recipients[$i];
}
}
if (count($unknowns) > 0) {
$to = array_shift($unknowns);
$cc = implode('; ', $unknowns);
// send direct emails
Support::sendDirectEmail($HTTP_POST_VARS['issue_id'], $from, $to, $cc, $HTTP_POST_VARS['subject'], $HTTP_POST_VARS['message'], $message_id, $sender_usr_id);
}
} else {
// send direct emails to all recipients, since we don't have an associated issue
$project_info = Project::getOutgoingSenderAddress(Auth::getCurrentProject());
// use the project-related outgoing email address, if there is one
if (!empty($project_info['email'])) {
$from = Mail_API::getFormattedName(User::getFullName(Auth::getUserID()), $project_info['email']);
} else {
// otherwise, use the real email address for the current user
$from = User::getFromHeader(Auth::getUserID());
}
// send direct emails
Support::sendDirectEmail($HTTP_POST_VARS['issue_id'], $from, $HTTP_POST_VARS['to'], $HTTP_POST_VARS['cc'], $HTTP_POST_VARS['subject'], $HTTP_POST_VARS['message'], $message_id);
}
}
$t = array('customer_id' => 'NULL', 'issue_id' => $HTTP_POST_VARS["issue_id"] ? $HTTP_POST_VARS["issue_id"] : 0, 'ema_id' => $HTTP_POST_VARS['ema_id'], 'message_id' => $message_id, 'date' => Date_API::getCurrentDateGMT(), 'from' => $HTTP_POST_VARS['from'], 'to' => $HTTP_POST_VARS['to'], 'cc' => @$HTTP_POST_VARS['cc'], 'subject' => @$HTTP_POST_VARS['subject'], 'body' => $HTTP_POST_VARS['message'], 'full_email' => $full_email, 'has_attachment' => 0);
// associate this new email with a customer, if appropriate
if (Auth::getCurrentRole() == User::getRoleID('Customer')) {
$customer_id = User::getCustomerID(Auth::getUserID());
if (!empty($customer_id) && $customer_id != -1) {
$t['customer_id'] = $customer_id;
}
}
$structure = Mime_Helper::decode($full_email, true, false);
$t['headers'] = $structure->headers;
$res = Support::insertEmail($t, $structure, $sup_id);
if (!empty($HTTP_POST_VARS["issue_id"])) {
// need to send a notification
Notification::notifyNewEmail(Auth::getUserID(), $HTTP_POST_VARS["issue_id"], $t, $internal_only, false, $type, $sup_id);
// mark this issue as updated
if (!empty($t['customer_id']) && $t['customer_id'] != 'NULL') {
Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'customer action');
} else {
if (!empty($sender_usr_id) && User::getRoleByUser($sender_usr_id, Issue::getProjectID($HTTP_POST_VARS['issue_id'])) > User::getRoleID('Customer')) {
Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'staff response');
} else {
Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'user response');
}
}
// save a history entry for this
History::add($HTTP_POST_VARS["issue_id"], Auth::getUserID(), History::getTypeID('email_sent'), 'Outgoing email sent by ' . User::getFullName(Auth::getUserID()));
// also update the last_response_date field for the associated issue
if (Auth::getCurrentRole() > User::getRoleID('Customer')) {
$stmt = "UPDATE\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n SET\n iss_last_response_date='" . Date_API::getCurrentDateGMT() . "'\n WHERE\n iss_id=" . Misc::escapeInteger($HTTP_POST_VARS["issue_id"]);
$GLOBALS["db_api"]->dbh->query($stmt);
$stmt = "UPDATE\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n SET\n iss_first_response_date='" . Date_API::getCurrentDateGMT() . "'\n WHERE\n iss_first_response_date IS NULL AND\n iss_id=" . Misc::escapeInteger($HTTP_POST_VARS["issue_id"]);
$GLOBALS["db_api"]->dbh->query($stmt);
}
}
return 1;
}
@($issue_id = $HTTP_POST_VARS["issue_id"] ? $HTTP_POST_VARS["issue_id"] : $HTTP_GET_VARS["id"]);
$tpl->assign("extra_title", "Issue #{$issue_id} Details");
// check if the requested issue is a part of the 'current' project. If it doesn't
// check if issue exists in another project and if it does, switch projects
$iss_prj_id = Issue::getProjectID($issue_id);
$auto_switched_from = false;
if (!empty($iss_prj_id) && $iss_prj_id != $prj_id && in_array($iss_prj_id, $associated_projects)) {
$cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
Auth::setCurrentProject($iss_prj_id, $cookie["remember"], true);
$auto_switched_from = $prj_id;
$prj_id = $iss_prj_id;
}
$details = Issue::getDetails($issue_id);
$tpl->assign("issue", $details);
// in the case of a customer user, also need to check if that customer has access to this issue
if ($role_id == User::getRoleID('customer') && User::getCustomerID($usr_id) != $details['iss_customer_id']) {
$tpl->assign("auth_customer", 'denied');
} elseif (!Issue::canAccess($issue_id, $usr_id)) {
$tpl->assign("auth_user", 'denied');
} else {
$associated_projects = @array_keys(Project::getAssocList($usr_id));
if (empty($details) || $details['iss_prj_id'] != $prj_id) {
$tpl->assign('issue', '');
} else {
// check if the requested issue is a part of one of the projects
// associated with this user
if (!@in_array($details['iss_prj_id'], $associated_projects)) {
$tpl->assign("auth_customer", 'denied');
} else {
$options = Issue::saveSearchParams();
$sides = Issue::getSides($issue_id, $options);
Workflow::prePage($prj_id, 'update');
// check if the requested issue is a part of the 'current' project. If it doesn't
// check if issue exists in another project and if it does, switch projects
$iss_prj_id = Issue::getProjectID($issue_id);
$auto_switched_from = false;
if (!empty($iss_prj_id) && $iss_prj_id != $prj_id && in_array($iss_prj_id, $associated_projects)) {
$cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
Auth::setCurrentProject($iss_prj_id, $cookie['remember'], true);
$auto_switched_from = $iss_prj_id;
$prj_id = $iss_prj_id;
Misc::setMessage(ev_gettext('Note: Project automatically switched to "%1$s" from "%2$s".', Auth::getCurrentProjectName(), Project::getName($iss_prj_id)));
}
$tpl->assign('issue', $details);
$tpl->assign('extra_title', ev_gettext('Update Issue #%1$s', $issue_id));
// in the case of a customer user, also need to check if that customer has access to this issue
if ($role_id == User::getRoleID('customer') && (empty($details) || User::getCustomerID($usr_id) != $details['iss_customer_id']) || !Issue::canAccess($issue_id, $usr_id) || !($role_id > User::getRoleID('Reporter')) || !Issue::canUpdate($issue_id, $usr_id)) {
$tpl->setTemplate('base_full.tpl.html');
Misc::setMessage(ev_gettext('Sorry, you do not have the required privileges to update this issue.'), Misc::MSG_ERROR);
$tpl->displayTemplate();
exit;
}
if (Issue_Lock::acquire($issue_id, $usr_id)) {
$issue_lock = false;
} else {
$issue_lock = Issue_Lock::getInfo($issue_id);
$issue_lock['locker'] = User::getDetails($issue_lock['usr_id']);
$issue_lock['expires_formatted_time'] = Date_Helper::getFormattedDate($issue_lock['expires']);
}
$tpl->assign('issue_lock', $issue_lock);
$new_prj_id = Issue::getProjectID($issue_id);
$cancel_update = isset($_POST['cancel']);
}
// if we are dealing with just one message, use the subject line as the
// summary for the issue, and the body as the description
if (count($HTTP_GET_VARS["item"]) == 1) {
$email_details = Support::getEmailDetails(Email_Account::getAccountByEmail($HTTP_GET_VARS["item"][0]), $HTTP_GET_VARS["item"][0]);
$tpl->assign(array('issue_summary' => $email_details['sup_subject'], 'issue_description' => $email_details['message']));
// also auto pre-fill the customer contact text fields
if (Customer::hasCustomerIntegration($prj_id)) {
$sender_email = Mail_API::getEmailAddress($email_details['sup_from']);
list(, $contact_id) = Customer::getCustomerIDByEmails($prj_id, array($sender_email));
if (!empty($contact_id)) {
$tpl->assign("contact_details", Customer::getContactDetails($prj_id, $contact_id));
}
}
}
}
}
$tpl->assign(array("cats" => Category::getAssocList($prj_id), "priorities" => Priority::getAssocList($prj_id), "users" => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')), "releases" => Release::getAssocList($prj_id), "custom_fields" => Custom_Field::getListByProject($prj_id, 'report_form'), "max_attachment_size" => Attachment::getMaxAttachmentSize(), "field_display_settings" => Project::getFieldDisplaySettings($prj_id), "groups" => Group::getAssocList($prj_id)));
$setup = Setup::load();
$tpl->assign("allow_unassigned_issues", @$setup["allow_unassigned_issues"]);
$prefs = Prefs::get($usr_id);
$tpl->assign("user_prefs", $prefs);
$tpl->assign("zones", Date_API::getTimezoneList());
if (User::getRole(Auth::getCurrentRole()) == "Customer") {
$customer_contact_id = User::getCustomerContactID($usr_id);
$tpl->assign("contact_details", Customer::getContactDetails($prj_id, $customer_contact_id));
$customer_id = User::getCustomerID($usr_id);
$tpl->assign("contacts", Customer::getContactEmailAssocList($prj_id, $customer_id));
$tpl->assign(array("customer_id" => User::getCustomerID($usr_id), "contact_id" => User::getCustomerContactID($usr_id)));
}
$tpl->displayTemplate();
/**
* Method used to get the list of issues to be displayed in the grid layout.
*
* @access public
* @param array $options The search parameters
* @return string The where clause
*/
function buildWhereClause($options)
{
$usr_id = Auth::getUserID();
$prj_id = Auth::getCurrentProject();
$role_id = User::getRoleByUser($usr_id, $prj_id);
$stmt = ' AND iss_usr_id = en_ID';
if (User::getRole($role_id) == "Customer") {
$stmt .= " AND iss_customer_id=" . User::getCustomerID($usr_id);
} elseif ($role_id <= User::getRoleID("Standard User") && Project::getSegregateReporters($prj_id)) {
$stmt .= " AND (\n iss_usr_id = {$usr_id} OR\n iur_usr_id = {$usr_id} OR\n isu_usr_id = {$usr_id}\n )";
}
if (!empty($options["users"])) {
$stmt .= " AND (\n";
if (stristr($options["users"], "grp") !== false) {
$chunks = explode(":", $options["users"]);
$stmt .= 'iss_grp_id = ' . Misc::escapeInteger($chunks[1]);
} else {
if ($options['users'] == '-1') {
$stmt .= 'isu_usr_id IS NULL';
} elseif ($options['users'] == '-2') {
$stmt .= 'isu_usr_id IS NULL OR isu_usr_id=' . $usr_id;
} elseif ($options['users'] == '-3') {
$stmt .= 'isu_usr_id = ' . $usr_id . ' OR iss_grp_id = ' . User::getGroupID($usr_id);
} elseif ($options['users'] == '-4') {
$stmt .= 'isu_usr_id IS NULL OR isu_usr_id = ' . $usr_id . ' OR iss_grp_id = ' . User::getGroupID($usr_id);
} else {
$stmt .= 'isu_usr_id =' . Misc::escapeInteger($options["users"]);
}
}
$stmt .= ')';
}
if (!empty($options["reporter"])) {
$stmt .= " AND iss_usr_id = " . Misc::escapeInteger($options["reporter"]);
}
if (!empty($options["show_authorized_issues"])) {
$stmt .= " AND (iur_usr_id={$usr_id})";
}
if (!empty($options["show_notification_list_issues"])) {
$stmt .= " AND (sub_usr_id={$usr_id})";
}
if (!empty($options["keywords"])) {
$stmt .= " AND (\n";
if ($options['search_type'] == 'all_text' && APP_ENABLE_FULLTEXT) {
$stmt .= "iss_id IN(" . join(', ', Issue::getFullTextIssues($options)) . ")";
} elseif ($options['search_type'] == 'customer' && Customer::hasCustomerIntegration($prj_id)) {
// check if the user is trying to search by customer email
$customer_ids = Customer::getCustomerIDsLikeEmail($prj_id, $options['keywords']);
if (count($customer_ids) > 0) {
$stmt .= " iss_customer_id IN (" . implode(', ', $customer_ids) . ")";
} else {
// no results, kill query
$stmt .= " iss_customer_id = -1";
}
} else {
$stmt .= "(" . Misc::prepareBooleanSearch('iss_summary', $options["keywords"]);
$stmt .= " OR " . Misc::prepareBooleanSearch('iss_description', $options["keywords"]) . ")";
}
$stmt .= "\n) ";
}
if (!empty($options["priority"])) {
$stmt .= " AND iss_pri_id=" . Misc::escapeInteger($options["priority"]);
}
if (!empty($options["status"])) {
$stmt .= " AND iss_sta_id=" . Misc::escapeInteger($options["status"]);
}
if (!empty($options["category"])) {
$stmt .= " AND iss_prc_id=" . Misc::escapeInteger($options["category"]);
}
if (!empty($options["hide_closed"])) {
$stmt .= " AND sta_is_closed=0";
}
if (!empty($options["hide_answered"])) {
$stmt .= " AND iss_control_status='Unanswered'";
}
if (!empty($options['release'])) {
$stmt .= " AND iss_pre_id = " . Misc::escapeInteger($options['release']);
}
// now for the date fields
$date_fields = array('created_date', 'updated_date', 'last_response_date', 'first_response_date', 'closed_date');
foreach ($date_fields as $field_name) {
if (!empty($options[$field_name])) {
switch ($options[$field_name]['filter_type']) {
case 'greater':
$stmt .= " AND iss_{$field_name} >= '" . Misc::escapeString($options[$field_name]['start']) . "'";
break;
case 'less':
$stmt .= " AND iss_{$field_name} <= '" . Misc::escapeString($options[$field_name]['start']) . "'";
break;
case 'between':
$stmt .= " AND iss_{$field_name} BETWEEN '" . Misc::escapeString($options[$field_name]['start']) . "' AND '" . Misc::escapeString($options[$field_name]['end']) . "'";
break;
case 'null':
$stmt .= " AND iss_{$field_name} IS NULL";
break;
case 'in_past':
if (strlen($options[$field_name]['time_period']) == 0) {
$options[$field_name]['time_period'] = 0;
}
$stmt .= " AND (UNIX_TIMESTAMP('" . Date_API::getCurrentDateGMT() . "') - UNIX_TIMESTAMP(iss_{$field_name})) <= (" . Misc::escapeInteger($options[$field_name]['time_period']) . "*3600)";
break;
case 'not_in_past':
if (strlen($options[$field_name]['time_period']) == 0) {
$options[$field_name]['time_period'] = 0;
}
$stmt .= " AND \n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tiss_{$field_name} is NULL || \n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t(UNIX_TIMESTAMP('" . Date_API::getCurrentDateGMT() . "') - UNIX_TIMESTAMP(iss_{$field_name})) > (" . Misc::escapeInteger($options[$field_name]['time_period']) . "*3600)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)";
break;
}
}
}
// custom fields
if (is_array($options['custom_field']) && count($options['custom_field']) > 0) {
foreach ($options['custom_field'] as $fld_id => $search_value) {
if (empty($search_value)) {
continue;
}
$field = Custom_Field::getDetails($fld_id);
if ($field['fld_type'] == 'multiple') {
$search_value = Misc::escapeInteger($search_value);
foreach ($search_value as $cfo_id) {
$stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . ".icf_iss_id = iss_id";
$stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . ".icf_fld_id = {$fld_id}";
$stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . ".icf_value = {$cfo_id}";
}
} elseif ($field['fld_type'] == 'date') {
if (empty($search_value['Year']) || empty($search_value['Month']) || empty($search_value['Day'])) {
continue;
}
$search_value = $search_value['Year'] . "-" . $search_value['Month'] . "-" . $search_value['Day'];
$stmt .= " AND\n (iss_id = cf" . $fld_id . ".icf_iss_id AND\n cf" . $fld_id . ".icf_value = '" . Misc::escapeString($search_value) . "')";
} else {
$stmt .= " AND\n (iss_id = cf" . $fld_id . ".icf_iss_id";
$stmt .= " AND\n cf" . $fld_id . ".icf_fld_id = {$fld_id}";
if (in_array($field['fld_type'], array('text', 'textarea'))) {
$stmt .= " AND cf" . $fld_id . ".icf_value LIKE '%" . Misc::escapeString($search_value) . "%'";
} elseif ($field['fld_type'] == 'combo') {
$stmt .= " AND cf" . $fld_id . ".icf_value IN(" . join(', ', Misc::escapeInteger($search_value)) . ")";
}
$stmt .= ')';
}
}
}
// clear cached full-text values if we are not searching fulltext anymore
if (APP_ENABLE_FULLTEXT && @$options['search_type'] != 'all_text') {
Session::set('fulltext_string', '');
Session::set('fulltext_issues', '');
}
return $stmt;
}
function handleExpiredCustomer($prj_id)
{
global $tpl;
if (Customer::hasCustomerIntegration($prj_id)) {
// check if customer is expired
$usr_id = Auth::getUserID();
$contact_id = User::getCustomerContactID($usr_id);
if (!empty($contact_id) && $contact_id != -1) {
$status = Customer::getContractStatus($prj_id, User::getCustomerID($usr_id));
$email = User::getEmailByContactID($contact_id);
if ($status == 'expired') {
Customer::sendExpirationNotice($prj_id, $contact_id, true);
Auth::saveLoginAttempt($email, 'failure', 'expired contract');
Auth::removeCookie(APP_PROJECT_COOKIE);
$contact_id = User::getCustomerContactID($usr_id);
$tpl->setTemplate("customer/" . Customer::getBackendImplementationName($prj_id) . "/customer_expired.tpl.html");
$tpl->assign('customer', Customer::getContractDetails($prj_id, $contact_id, false));
$tpl->displayTemplate();
exit;
} elseif ($status == 'in_grace_period') {
Customer::sendExpirationNotice($prj_id, $contact_id);
$tpl->setTemplate("customer/" . Customer::getBackendImplementationName($prj_id) . "/grace_period.tpl.html");
$tpl->assign('customer', Customer::getContractDetails($prj_id, $contact_id, false));
$tpl->assign('expiration_offset', Customer::getExpirationOffset($prj_id));
$tpl->displayTemplate();
exit;
}
// check with cnt_support to see if this contact is allowed in this support contract
if (!Customer::isAllowedSupportContact($prj_id, $contact_id)) {
Auth::saveLoginAttempt($email, 'failure', 'not allowed as technical contact');
Auth::redirect(APP_RELATIVE_URL . "index.php?err=4&email=" . $email);
}
}
}
}