/** * Returns the columns that should be displayed for the specified page. * This method will remove columns that should not be displayed, due to * lack of customer integration or insufficient role. * * @param integer $prj_id The ID of the project. * @param string $page The page to return columns for. * @return array An array of columns that should be displayed. */ public static function getColumnsToDisplay($prj_id, $page) { static $returns; // poor man's caching system if (!empty($returns[$prj_id][$page])) { return $returns[$prj_id][$page]; } $current_role = Auth::getCurrentRole(); $data = self::getSelectedColumns($prj_id, $page); $has_customer_integration = CRM::hasCustomerIntegration($prj_id); $only_with_customers = array('iss_customer_id', 'support_level'); // remove groups if there are no groups in the system. if (count(Group::getAssocList($prj_id)) < 1) { unset($data['iss_grp_id']); } // remove category column if there are no categories in the system if (count(Category::getAssocList($prj_id)) < 1) { unset($data['prc_title']); } // remove custom fields column if there are no custom fields if (count(Custom_Field::getFieldsToBeListed($prj_id)) < 1) { unset($data['custom_fields']); } // remove customer field if user has a role of customer if ($current_role == User::getRoleID('Customer')) { unset($data['iss_customer_id']); } foreach ($data as $field => $info) { // remove fields based on role if ($info['min_role'] > $current_role) { unset($data[$field]); continue; } // remove fields based on customer integration if (!$has_customer_integration && in_array($field, $only_with_customers)) { unset($data[$field]); continue; } // get title $data[$field] = self::getColumnInfo($page, $field); if (!isset($data[$field]['width'])) { $data[$field]['width'] = ''; } } $returns[$prj_id][$page] = $data; return $data; }
public function __construct() { $this->usr_id = Auth::getUserID(); if (!Access::canAccessReports($this->usr_id)) { throw new LogicException('Invalid role'); } $this->prj_id = Auth::getCurrentProject(); $this->activity_types = !empty($_REQUEST['activity_types']) ? (array) $_REQUEST['activity_types'] : array(); $this->report_type = isset($_REQUEST['report_type']) ? (string) $_REQUEST['report_type'] : null; $this->unit = $this->getParam('unit', array('hour', 'day')); $this->amount = isset($_REQUEST['amount']) ? $_REQUEST['amount'] : null; $this->developer = isset($_REQUEST['developer']) ? $_REQUEST['developer'] : null; $this->start_date = $this->parseDate(isset($_POST['start']) ? $_POST['start'] : null); $this->end_date = $this->parseDate(isset($_POST['end']) ? $_POST['end'] : null); $this->sort_order = $this->getParam('sort_order', array('ASC', 'DESC')); if (CRM::hasCustomerIntegration($this->prj_id)) { $this->crm = CRM::getInstance($this->prj_id); } }
/** * Attach uploaded files to an issue * It also notifies any subscribers of this new attachment. * * @param int $issue_id The issue ID * @param int $usr_id The user ID * @param int[] $iaf_ids attachment file id-s to attach * @param boolean $internal_only Whether this attachment is supposed to be internal only or not * @param string $file_description File description text * @param string $unknown_user The email of the user who originally sent this email, who doesn't have an account. * @param integer $associated_note_id The note ID that these attachments should be associated with */ public static function attachFiles($issue_id, $usr_id, $iaf_ids, $internal_only, $file_description, $unknown_user = null, $associated_note_id = null) { if (!$iaf_ids) { throw new LogicException('No attachment ids'); } $attachment_id = self::add($issue_id, $usr_id, $file_description, $internal_only, $unknown_user, $associated_note_id); self::associateFiles($attachment_id, $iaf_ids); Issue::markAsUpdated($issue_id, 'file uploaded'); History::add($issue_id, $usr_id, 'attachment_added', 'Attachment uploaded by {user}', array('user' => User::getFullName($usr_id))); // if there is customer integration, mark last customer action $prj_id = Issue::getProjectID($issue_id); $has_crm = CRM::hasCustomerIntegration($prj_id); $is_customer = User::getRoleByUser($usr_id, $prj_id) == User::ROLE_CUSTOMER; if ($has_crm && $is_customer) { Issue::recordLastCustomerAction($issue_id); } Workflow::handleAttachment($prj_id, $issue_id, $usr_id); Notification::notify($issue_id, 'files', $attachment_id, $internal_only); }
// +----------------------------------------------------------------------+ require_once dirname(__FILE__) . '/../init.php'; $tpl = new Template_Helper(); $tpl->setTemplate('select_customer.tpl.html'); session_start(); // check if cookies are enabled, first of all if (!Auth::hasCookieSupport(APP_COOKIE)) { Auth::redirect('index.php?err=11'); } if (!Auth::hasValidCookie(APP_COOKIE)) { Auth::redirect('index.php?err=5'); } $prj_id = Auth::getCurrentProject(); $usr_id = Auth::getUserID(); $contact_id = User::getCustomerContactID($usr_id); if (!CRM::hasCustomerIntegration($prj_id) || empty($contact_id)) { Auth::redirect('main.php'); } $crm = CRM::getInstance($prj_id); $contact = $crm->getContact($contact_id); $customers = $contact->getCustomers(); if (isset($_REQUEST['customer_id'])) { $customer_id = $_REQUEST['customer_id']; if (in_array($customer_id, array_keys($customers))) { Auth::setCurrentCustomerID($customer_id); if (!empty($_POST['url'])) { Auth::redirect($_REQUEST['url']); } else { Auth::redirect('main.php'); } }
Misc::setMessage(ev_gettext('Sorry, you are not allowed to access this page.'), Misc::MSG_ERROR); $tpl->displayTemplate(); exit; } $tpl->assign('project_list', Project::getAll()); if (@$_POST['cat'] == 'new') { $res = Custom_Field::insert(); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the custom field was added successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to add the new custom field.'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'update') { $res = Custom_Field::update(); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the custom field was updated successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to update the custom field information.'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'delete') { $res = Custom_Field::remove(); Misc::mapMessages($res, array(true => array(ev_gettext('Thank you, the custom field was removed successfully.'), Misc::MSG_INFO), false => array(ev_gettext('An error occurred while trying to remove the custom field information.'), Misc::MSG_ERROR))); } elseif (@$_REQUEST['cat'] == 'change_rank') { Custom_Field::changeRank(); } if (@$_GET['cat'] == 'edit') { $tpl->assign('info', Custom_Field::getDetails($_GET['id'])); } $excluded_roles = array(); if (!CRM::hasCustomerIntegration(Auth::getCurrentProject())) { $excluded_roles[] = 'customer'; } $user_roles = User::getRoles($excluded_roles); $user_roles[9] = 'Never Display'; $tpl->assign('list', Custom_Field::getList()); $tpl->assign('project_list', Project::getAll()); $tpl->assign('user_roles', $user_roles); $tpl->assign('backend_list', Custom_Field::getBackendList()); $tpl->displayTemplate();
// wouldn't make much sense to create a reminder for a 'Not Prioritized' // issue, so let's remove that as an option $priorities = array_flip(Priority::getAssocList($info['rem_prj_id'])); unset($priorities['Not Prioritized']); $tpl->assign('priorities', array_flip($priorities)); $tpl->assign('severities', Severity::getAssocList($info['rem_prj_id'])); $tpl->assign('products', Product::getAssocList()); } elseif (@$_GET['cat'] == 'change_rank') { Reminder::changeRank($_GET['id'], $_GET['rank']); } elseif (!empty($_GET['prj_id'])) { $tpl->assign('info', array('rem_prj_id' => $_GET['prj_id'])); $tpl->assign('issues', Reminder::getIssueAssocListByProject($_GET['prj_id'])); // wouldn't make much sense to create a reminder for a 'Not Prioritized' // issue, so let's remove that as an option $priorities = array_flip(Priority::getAssocList($_GET['prj_id'])); unset($priorities['Not Prioritized']); $tpl->assign('priorities', array_flip($priorities)); $tpl->assign('severities', Severity::getAssocList($_GET['prj_id'])); $tpl->assign('products', Product::getAssocList()); // only show customers and support levels if the selected project really needs it $project_has_customer_integration = CRM::hasCustomerIntegration($_GET['prj_id']); $tpl->assign('project_has_customer_integration', $project_has_customer_integration); if ($project_has_customer_integration) { $crm = CRM::getInstance($_GET['prj_id']); $tpl->assign('customers', $crm->getCustomerAssocList()); $tpl->assign('support_levels', $crm->getSupportLevelAssocList()); } } $tpl->assign('project_list', Project::getAll()); $tpl->assign('list', Reminder::getAdminList()); $tpl->displayTemplate();
if ($role_id < User::getRoleID('administrator')) { Misc::setMessage(ev_gettext('Sorry, you are not allowed to access this page.'), Misc::MSG_ERROR); $tpl->displayTemplate(); exit; } $tpl->assign('project_list', Project::getAll()); if (@$_POST['cat'] == 'new') { $res = Status::insertCustomization($_POST['project'], $_POST['status'], $_POST['date_field'], $_POST['label']); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the customization was added successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to add the new customization.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this new customization'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'update') { $res = Status::updateCustomization($_POST['id'], $_POST['project'], $_POST['status'], $_POST['date_field'], $_POST['label']); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the customization was updated successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to update the customization information.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this customization.'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'delete') { $res = Status::removeCustomization(@$_POST['items']); Misc::mapMessages($res, array(true => array(ev_gettext('Thank you, the customization was deleted successfully.'), Misc::MSG_INFO), false => array(ev_gettext('An error occurred while trying to delete the customization information.'), Misc::MSG_ERROR))); } if (@$_GET['cat'] == 'edit') { $details = Status::getCustomizationDetails($_GET['id']); $tpl->assign(array('info' => $details, 'project_id' => $details['psd_prj_id'], 'status_list' => Status::getAssocStatusList($details['psd_prj_id'], true))); } $display_customer_fields = false; @($prj_id = $_POST['prj_id'] ? $_POST['prj_id'] : $_GET['prj_id']); if (!empty($prj_id)) { $tpl->assign('status_list', Status::getAssocStatusList($prj_id, true)); $tpl->assign('project_id', $prj_id); $display_customer_fields = CRM::hasCustomerIntegration($prj_id); } $tpl->assign('date_fields', Issue::getDateFieldsAssocList($display_customer_fields)); $tpl->assign('project_list', Project::getAll()); $tpl->assign('list', Status::getCustomizationList()); $tpl->displayTemplate();
/** * Method used to get the details for a specific issue. * * @param integer $issue_id The issue ID * @param boolean $force_refresh If the cache should not be used. * @return array The details for the specified issue */ public static function getDetails($issue_id, $force_refresh = false) { static $returns; if (empty($issue_id)) { return ''; } if (!empty($returns[$issue_id]) && $force_refresh != true) { return $returns[$issue_id]; } $stmt = 'SELECT {{%issue}}.*, prj_title, prc_title, pre_title, pri_title, sev_title, sta_title, sta_abbreviation, sta_color status_color, sta_is_closed FROM ( {{%issue}}, {{%project}} ) LEFT JOIN {{%project_priority}} ON iss_pri_id=pri_id LEFT JOIN {{%project_severity}} ON iss_sev_id=sev_id LEFT JOIN {{%status}} ON iss_sta_id=sta_id LEFT JOIN {{%project_category}} ON iss_prc_id=prc_id LEFT JOIN {{%project_release}} ON iss_pre_id=pre_id WHERE iss_id=? AND iss_prj_id=prj_id'; try { $res = DB_Helper::getInstance()->getRow($stmt, array($issue_id)); } catch (DbException $e) { return ''; } if (empty($res)) { return ''; } $created_date_ts = Date_Helper::getUnixTimestamp($res['iss_created_date'], Date_Helper::getDefaultTimezone()); // get customer information, if any if (!empty($res['iss_customer_id']) && CRM::hasCustomerIntegration($res['iss_prj_id'])) { $crm = CRM::getInstance($res['iss_prj_id']); try { $customer = $crm->getCustomer($res['iss_customer_id']); $contract = $crm->getContract($res['iss_customer_contract_id']); $res['contact_local_time'] = Date_Helper::getFormattedDate(Date_Helper::getCurrentDateGMT(), $res['iss_contact_timezone']); $res['customer'] = $customer; $res['contract'] = $contract; $res['contact'] = $crm->getContact($res['iss_customer_contact_id']); // TODOCRM: Deal with incidents // $res['redeemed_incidents'] = Customer::getRedeemedIncidentDetails($res['iss_prj_id'], $res['iss_id']); $max_first_response_time = $contract->getMaximumFirstResponseTime($issue_id); $res['max_first_response_time'] = Misc::getFormattedTime($max_first_response_time / 60); if (empty($res['iss_first_response_date'])) { $first_response_deadline = $created_date_ts + $max_first_response_time; if (time() <= $first_response_deadline) { $res['max_first_response_time_left'] = Date_Helper::getFormattedDateDiff($first_response_deadline, time()); } else { $res['overdue_first_response_time'] = Date_Helper::getFormattedDateDiff(time(), $first_response_deadline); } } } catch (CRMException $e) { // TODOCRM: Log exception? } } $res['iss_original_description'] = $res['iss_description']; $res['iss_original_percent_complete'] = $res['iss_percent_complete']; $res['iss_description'] = nl2br(htmlspecialchars($res['iss_description'])); $res['iss_resolution'] = Resolution::getTitle($res['iss_res_id']); $res['iss_impact_analysis'] = nl2br(htmlspecialchars($res['iss_impact_analysis'])); $res['iss_created_date_ts'] = $created_date_ts; $res['assignments'] = @implode(', ', array_values(self::getAssignedUsers($res['iss_id']))); list($res['authorized_names'], $res['authorized_repliers']) = Authorized_Replier::getAuthorizedRepliers($res['iss_id']); $temp = self::getAssignedUsersStatus($res['iss_id']); $res['has_inactive_users'] = 0; $res['assigned_users'] = array(); $res['assigned_inactive_users'] = array(); foreach ($temp as $usr_id => $usr_status) { if (!User::isActiveStatus($usr_status)) { $res['assigned_inactive_users'][] = $usr_id; $res['has_inactive_users'] = 1; } else { $res['assigned_users'][] = $usr_id; } } if (@in_array(Auth::getUserID(), $res['assigned_users'])) { $res['is_current_user_assigned'] = 1; } else { $res['is_current_user_assigned'] = 0; } $res['associated_issues_details'] = self::getAssociatedIssuesDetails($res['iss_id']); $res['associated_issues'] = self::getAssociatedIssues($res['iss_id']); $res['reporter'] = User::getFullName($res['iss_usr_id']); if (empty($res['iss_updated_date'])) { $res['iss_updated_date'] = $res['iss_created_date']; } $res['estimated_formatted_time'] = Misc::getFormattedTime($res['iss_dev_time']); if (Release::isAssignable($res['iss_pre_id'])) { $release = Release::getDetails($res['iss_pre_id']); $res['pre_title'] = $release['pre_title']; $res['pre_status'] = $release['pre_status']; } // need to return the list of issues that are duplicates of this one $res['duplicates'] = self::getDuplicateList($res['iss_id']); $res['duplicates_details'] = self::getDuplicateDetailsList($res['iss_id']); // also get the issue title of the duplicated issue if (!empty($res['iss_duplicated_iss_id'])) { $res['duplicated_issue'] = self::getDuplicatedDetails($res['iss_duplicated_iss_id']); } // get group information if (!empty($res['iss_grp_id'])) { $res['group'] = Group::getDetails($res['iss_grp_id']); } // get quarantine issue $res['quarantine'] = self::getQuarantineInfo($res['iss_id']); $res['products'] = Product::getProductsByIssue($res['iss_id']); $returns[$issue_id] = $res; return $res; }
// if currently selected release is in the past, manually add it to list $releases = Release::getAssocList($prj_id); if ($details['iss_pre_id'] != 0 && empty($releases[$details['iss_pre_id']])) { $releases = array($details['iss_pre_id'] => $details['pre_title']) + $releases; } if (Workflow::hasWorkflowIntegration($prj_id)) { $statuses = Workflow::getAllowedStatuses($prj_id, $issue_id); // if currently selected release is not on list, go ahead and add it. } else { $statuses = Status::getAssocStatusList($prj_id, false); } if (!empty($details['iss_sta_id']) && empty($statuses[$details['iss_sta_id']])) { $statuses[$details['iss_sta_id']] = Status::getStatusTitle($details['iss_sta_id']); } $columns = array(0 => array(), 1 => array()); if (CRM::hasCustomerIntegration($prj_id) and !empty($details['iss_customer_id'])) { $columns[0][] = array('title' => 'Customer', 'field' => 'customer_0'); $columns[1][] = array('title' => 'Customer Contract', 'field' => 'customer_1'); } $categories = Category::getAssocList($prj_id); if (count($categories) > 0) { $columns[0][] = array('title' => ev_gettext('Category'), 'data' => $details['prc_title'], 'field' => 'category'); } $columns[0][] = array('title' => ev_gettext('Status'), 'data' => $details['sta_title'], 'data_bgcolor' => $details['status_color'], 'field' => 'status'); $severities = Severity::getAssocList($prj_id); if (count($severities) > 0) { $columns[0][] = array('title' => ev_gettext('Severity'), 'data' => $details['sev_title'], 'field' => 'severity'); } $priorities = Priority::getAssocList($prj_id); if (count($priorities) > 0 && (!isset($issue_fields_display['priority']) || $issue_fields_display['priority'] != false)) { if (isset($issue_fields_display['priority']['min_role']) && $issue_fields_display['priority']['min_role'] > User::getRoleID('Customer')) {
/** * Method used to get the list of associated support levels for a given * FAQ entry. * * @param integer $prj_id The project ID * @param integer $faq_id The FAQ ID * @return array The list of projects */ public function getAssociatedSupportLevels($prj_id, $faq_id) { if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); $stmt = 'SELECT fsl_support_level_id FROM {{%faq_support_level}} WHERE fsl_faq_id=?'; $ids = DB_Helper::getInstance()->getColumn($stmt, array($faq_id)); $t = array(); $levels = $crm->getSupportLevelAssocList(); foreach ($levels as $support_level_id => $support_level) { if (in_array($support_level_id, $ids)) { $t[$support_level_id] = $support_level; } } return $t; } else { return array(); } }
/** * Method used to generate a where clause from the given list of conditions. * * @param array $reminder An array of reminder info. * @param array $conditions The list of conditions * @return string The where clause */ public function getWhereClause($reminder, $conditions) { $stmt = ' WHERE iss_prj_id=' . $reminder['rem_prj_id'] . "\n"; $requirement = self::getRequirements($reminder['rem_id']); if ($requirement['type'] == 'issue') { $stmt .= ' AND iss_id IN (' . implode(', ', $requirement['values']) . ")\n"; } else { if (CRM::hasCustomerIntegration($reminder['rem_prj_id'])) { $crm = CRM::getInstance($reminder['rem_prj_id']); if ($requirement['type'] == 'customer') { $stmt .= ' AND iss_customer_id IN (' . implode(', ', $requirement['values']) . ")\n"; } elseif ($requirement['type'] == 'support_level') { $customer_ids = $crm->getCustomerIDsBySupportLevel($requirement['values'], array(CRM_EXCLUDE_EXPIRED)); // break the query on purpose if no customers could be found if (count($customer_ids) == 0) { $customer_ids = array(-1); } $stmt .= ' AND iss_customer_id IN (' . implode(', ', $customer_ids) . ")\n"; } } } $priorities = self::getAssociatedPriorities($reminder['rem_id']); if (count($priorities) > 0) { $stmt .= ' AND iss_pri_id IN (' . implode(', ', $priorities) . ")\n"; } $products = self::getAssociatedProducts($reminder['rem_id']); if (count($products) > 0) { $stmt .= ' AND ipv_iss_id = iss_id AND ipv_pro_id IN (' . implode(', ', $products) . ")\n"; } $severities = self::getAssociatedSeverities($reminder['rem_id']); if (count($severities) > 0) { $stmt .= ' AND iss_sev_id IN (' . implode(', ', $severities) . ")\n"; } // now for the interesting stuff foreach ($conditions as &$cond) { if (empty($cond['rmf_sql_representation'])) { continue; } // check for fields that compare to other fields if (!empty($cond['rlc_comparison_rmf_id'])) { $sql_field = Reminder_Condition::getSQLField($cond['rlc_comparison_rmf_id']); $stmt .= sprintf(" AND %s %s %s\n", $cond['rmf_sql_field'], $cond['rmo_sql_representation'], $sql_field); } else { // date field values are always saved as number of hours, so let's calculate them now as seconds if (stristr($cond['rmf_title'], 'date')) { // support NULL as values for a date field if (strtoupper($cond['rlc_value']) == 'NULL') { $cond['rmf_sql_representation'] = $cond['rmf_sql_field']; } elseif (strtoupper($cond['rlc_value']) == 'NOW') { $cond['rmf_sql_representation'] = 'UNIX_TIMESTAMP(' . $cond['rmf_sql_field'] . ')'; $cond['rlc_value'] = 'UNIX_TIMESTAMP()'; } else { $cond['rlc_value'] = $cond['rlc_value'] * 60 * 60; if (@$reminder['rem_skip_weekend'] == 1) { $sql_field = Reminder_Condition::getSQLField($cond['rlc_rmf_id']); $cond['rmf_sql_representation'] = DB_Helper::getNoWeekendDateDiffSQL($sql_field); } } } $stmt .= sprintf(" AND %s %s %s\n", $cond['rmf_sql_representation'], $cond['rmo_sql_representation'], $cond['rlc_value']); } } return $stmt; }
if (@$_POST['cat'] == 'new') { $res = FAQ::insert(); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the FAQ entry was added successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to add the FAQ entry.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this FAQ entry.'), Misc::MSG_ERROR), -3 => array(ev_gettext('Please enter the message for this FAQ entry.'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'update') { $res = FAQ::update(); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the FAQ entry was updated successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to update the FAQ entry information.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this FAQ entry.'), Misc::MSG_ERROR), -3 => array(ev_gettext('Please enter the message for this FAQ entry.'), Misc::MSG_ERROR))); } elseif (@$_POST['cat'] == 'delete') { FAQ::remove(); } elseif (!empty($_GET['prj_id'])) { $tpl->assign('info', array('faq_prj_id' => $_GET['prj_id'])); if (CRM::hasCustomerIntegration($_GET['prj_id'])) { $crm = CRM::getInstance($_GET['prj_id']); $tpl->assign('support_levels', $crm->getSupportLevelAssocList()); } } if (@$_GET['cat'] == 'edit') { $info = FAQ::getDetails($_GET['id']); if (!empty($_GET['prj_id'])) { $info['faq_prj_id'] = $_GET['prj_id']; } if (CRM::hasCustomerIntegration($info['faq_prj_id'])) { $crm = CRM::getInstance($info['faq_prj_id']); $tpl->assign('support_levels', $crm->getSupportLevelAssocList()); } $tpl->assign('info', $info); } elseif (@$_GET['cat'] == 'change_rank') { FAQ::changeRank($_GET['id'], $_GET['rank']); } $tpl->assign('list', FAQ::getList()); $tpl->assign('project_list', Project::getAll()); $tpl->displayTemplate();
/** * Method used to send an alert to a set of email addresses when * a reminder action was triggered, but no action was really * taken because no recipients could be found. * * @param integer $issue_id The issue ID * @param string $type Which reminder are we trying to send, email or sms * @param array $reminder The reminder details * @param array $action The action details * @return void */ private function _recordNoRecipientError($issue_id, $type, $reminder, $action, $data, $conditions) { $to = Reminder::_getReminderAlertAddresses(); if (count($to) > 0) { $tpl = new Template_Helper(); $tpl->setTemplate('reminders/alert_no_recipients.tpl.text'); $tpl->assign(array('type' => $type, 'data' => $data, 'reminder' => $reminder, 'action' => $action, 'conditions' => $conditions, 'has_customer_integration' => CRM::hasCustomerIntegration(Issue::getProjectID($issue_id)))); $text_message = $tpl->getTemplateContents(); foreach ($to as $address) { // send email (use PEAR's classes) $mail = new Mail_Helper(); $mail->setTextBody($text_message); $setup = $mail->getSMTPSettings(); // TRANSLATORS: %1 = issue_id, %2 - rma_title $subject = ev_gettext('[#%1$s] Reminder Not Triggered: [#%2$s]', $issue_id, $action['rma_title']); $mail->send($setup['from'], $address, $subject, 0, $issue_id); } } }
/** * 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. * * @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 */ public static function checkAuthentication($failed_url = null, $is_popup = false) { try { self::getAuthBackend()->checkAuthentication(); if ($failed_url == null) { $failed_url = APP_RELATIVE_URL . 'index.php?err=5'; } $failed_url .= '&url=' . urlencode($_SERVER['REQUEST_URI']); if (!AuthCookie::hasAuthCookie()) { if (APP_ANON_USER) { $anon_usr_id = User::getUserIDByEmail(APP_ANON_USER); $prj_id = reset(array_keys(Project::getAssocList($anon_usr_id))); AuthCookie::setAuthCookie(APP_ANON_USER, false); AuthCookie::setProjectCookie($prj_id); Session::init($anon_usr_id); } else { // check for valid HTTP_BASIC params if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { if (self::isCorrectPassword($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { $usr_id = User::getUserIDByEmail($_SERVER['PHP_AUTH_USER'], true); $prj_id = reset(array_keys(Project::getAssocList($usr_id))); AuthCookie::setAuthCookie(APP_ANON_USER); AuthCookie::setProjectCookie($prj_id); } else { header('WWW-Authenticate: Basic realm="Eventum"'); header('HTTP/1.0 401 Unauthorized'); echo 'Login Failed'; return; } } else { self::redirect($failed_url, $is_popup); } } } $cookie = AuthCookie::getAuthCookie(); if (!$cookie) { AuthCookie::removeAuthCookie(); self::redirect($failed_url, $is_popup); } if (self::isPendingUser($cookie['email'])) { AuthCookie::removeAuthCookie(); self::redirect('index.php?err=9', $is_popup); } if (!self::isActiveUser($cookie['email'])) { AuthCookie::removeAuthCookie(); self::redirect('index.php?err=7', $is_popup); } $usr_id = self::getUserID(); // check the session Session::verify($usr_id); if (!defined('SKIP_LANGUAGE_INIT')) { Language::setPreference(); } // check whether the project selection is set or not $prj_id = self::getCurrentProject(); if (empty($prj_id)) { // redirect to select project page self::redirect(APP_RELATIVE_URL . 'select_project.php?url=' . urlencode($_SERVER['REQUEST_URI']), $is_popup); } // check the expiration date for a 'Customer' type user $contact_id = User::getCustomerContactID($usr_id); if (!empty($contact_id) && CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); $crm->authenticateCustomer(); } // auto switch project if (isset($_GET['switch_prj_id'])) { AuthCookie::setProjectCookie($_GET['switch_prj_id']); self::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 AuthCookie::setAuthCookie($cookie['email'], $cookie['permanent']); // renew the project cookie as well AuthCookie::setProjectCookie($prj_id); } catch (AuthException $e) { $tpl = new Template_Helper(); $tpl->setTemplate('authentication_error.tpl.html'); $tpl->assign('error_message', $e->getMessage()); $tpl->displayTemplate(); exit; } }
/** * Generates the specialized headers for an email. * * @param integer $issue_id The issue ID * @param string $type The type of message this is * @param string $headers The existing headers of this message. * @param integer $sender_usr_id The id of the user sending this email. * @return array An array of specialized headers */ public static function getSpecializedHeaders($issue_id, $type, $headers, $sender_usr_id) { $new_headers = array(); if (!empty($issue_id)) { $prj_id = Issue::getProjectID($issue_id); if (count(Group::getAssocList($prj_id)) > 0) { // group issue is currently assigned too $new_headers['X-Eventum-Group-Issue'] = Group::getName(Issue::getGroupID($issue_id)); // group of whoever is sending this message. if (empty($sender_usr_id)) { $new_headers['X-Eventum-Group-Replier'] = $new_headers['X-Eventum-Group-Issue']; } else { $new_headers['X-Eventum-Group-Replier'] = Group::getName(User::getGroupID($sender_usr_id)); } // group of current assignee $assignees = Issue::getAssignedUserIDs($issue_id); if (empty($assignees[0])) { $new_headers['X-Eventum-Group-Assignee'] = ''; } else { $new_headers['X-Eventum-Group-Assignee'] = @Group::getName(User::getGroupID($assignees[0])); } } if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); try { $customer = $crm->getCustomer(Issue::getCustomerID($issue_id)); $new_headers['X-Eventum-Customer'] = $customer->getName(); } catch (CustomerNotFoundException $e) { } try { $contract = $crm->getContract(Issue::getContractID($issue_id)); $support_level = $contract->getSupportLevel(); if (is_object($support_level)) { $new_headers['X-Eventum-Level'] = $support_level->getName(); } } catch (ContractNotFoundException $e) { } } // add assignee header $new_headers['X-Eventum-Assignee'] = implode(',', User::getEmail(Issue::getAssignedUserIDs($issue_id))); $new_headers['X-Eventum-Category'] = Category::getTitle(Issue::getCategory($issue_id)); $new_headers['X-Eventum-Project'] = Project::getName($prj_id); $new_headers['X-Eventum-Priority'] = Priority::getTitle(Issue::getPriority($issue_id)); // handle custom fields $cf_values = Custom_Field::getValuesByIssue($prj_id, $issue_id); $cf_titles = Custom_Field::getFieldsToBeListed($prj_id); foreach ($cf_values as $fld_id => $values) { // skip empty titles // TODO: why they are empty? if (!isset($cf_titles[$fld_id])) { continue; } // skip empty values if (empty($values)) { continue; } $cf_value = implode(', ', (array) $values); // value could be empty after multivalued field join if (empty($cf_value)) { continue; } // convert spaces for header fields $cf_title = str_replace(' ', '_', $cf_titles[$fld_id]); $new_headers['X-Eventum-CustomField-' . $cf_title] = $cf_value; } } $new_headers['X-Eventum-Type'] = $type; return $new_headers; }
/** * Method used to get the list of issues to be displayed in the grid layout. * * @param array $options The search parameters * @return string The where clause */ public static function buildWhereClause($options) { $usr_id = Auth::getUserID(); $prj_id = Auth::getCurrentProject(); $role_id = User::getRoleByUser($usr_id, $prj_id); $usr_details = User::getDetails($usr_id); $stmt = ' AND iss_usr_id = usr_id'; if ($role_id == User::getRoleID('Customer')) { $crm = CRM::getInstance($prj_id); $contact = $crm->getContact($usr_details['usr_customer_contact_id']); $stmt .= " AND iss_customer_contract_id IN('" . implode("','", $contact->getContractIDS()) . "')"; $stmt .= " AND iss_customer_id ='" . Auth::getCurrentCustomerID() . "'"; } elseif ($role_id == User::getRoleID('Reporter') && Project::getSegregateReporters($prj_id)) { $stmt .= " AND (\n iss_usr_id = {$usr_id} OR\n iur_usr_id = {$usr_id}\n )"; } if (!empty($usr_details['usr_par_code'])) { // restrict partners $stmt .= " AND ipa_par_code = '" . Misc::escapeString($usr_details['usr_par_code']) . "'"; } 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(' . implode(', ', self::getFullTextIssues($options)) . ')'; } elseif ($options['search_type'] == 'customer' && CRM::hasCustomerIntegration($prj_id)) { // check if the user is trying to search by customer name / email $crm = CRM::getInstance($prj_id); $customer_ids = $crm->getCustomerIDsByString($options['keywords'], true); 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['customer_id'])) { $stmt .= " AND iss_customer_id='" . Misc::escapeString($options['customer_id']) . "'"; } 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'])) { if (!is_array($options['category'])) { $options['category'] = array($options['category']); } $stmt .= ' AND iss_prc_id IN(' . implode(', ', Misc::escapeInteger($options['category'])) . ')'; } if (!empty($options['hide_closed'])) { $stmt .= ' AND sta_is_closed=0'; } if (!empty($options['release'])) { $stmt .= ' AND iss_pre_id = ' . Misc::escapeInteger($options['release']); } if (!empty($options['product'])) { $stmt .= ' AND ipv_pro_id = ' . Misc::escapeInteger($options['product']); } // 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_Helper::getCurrentDateGMT() . "') - UNIX_TIMESTAMP(iss_{$field_name})) <= (" . Misc::escapeInteger($options[$field_name]['time_period']) . '*3600)'; 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); $fld_db_name = Custom_Field::getDBValueFieldNameByType($field['fld_type']); if ($field['fld_type'] == 'date' && (empty($search_value['Year']) || empty($search_value['Month']) || empty($search_value['Day']))) { continue; } if ($field['fld_type'] == 'integer' && empty($search_value['value'])) { continue; } if ($field['fld_type'] == 'multiple') { $search_value = Misc::escapeString($search_value); foreach ($search_value as $cfo_id) { $cfo_id = Misc::escapeString($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 . '.' . $fld_db_name . " = '{$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 cf' . $fld_id . '.' . $fld_db_name . " = '" . Misc::escapeString($search_value) . "')"; } elseif ($field['fld_type'] == 'integer') { $value = $search_value['value']; switch ($search_value['filter_type']) { case 'ge': $cmp = '>='; break; case 'le': $cmp = '<='; break; case 'gt': $cmp = '>'; break; case 'lt': $cmp = '<'; break; default: $cmp = '='; break; } $stmt .= " AND\n (iss_id = cf" . $fld_id . '.icf_iss_id'; $stmt .= " AND\n cf" . $fld_id . ".icf_fld_id = {$fld_id}"; $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . $cmp . Misc::escapeString($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 ($field['fld_type'] == 'combo') { $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . " IN('" . implode("', '", Misc::escapeString($search_value)) . "')"; } else { $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . " LIKE '%" . Misc::escapeString($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 checkCustomerAuthentication($prj_id) { if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); // check if customer is expired $usr_id = Auth::getUserID(); $contact_id = User::getCustomerContactID($usr_id); if (User::getRoleByUser($usr_id, $prj_id) == User::ROLE_CUSTOMER) { $crm->authenticateCustomer(); } } }
/** * Checks whether the given email address is allowed to send emails in the * issue ID. * * @param integer $issue_id The issue ID * @param string $sender_email The email address * @return boolean */ public static function isAllowedToEmail($issue_id, $sender_email) { $prj_id = Issue::getProjectID($issue_id); // check the workflow $workflow_can_email = Workflow::canEmailIssue($prj_id, $issue_id, $sender_email); if ($workflow_can_email != null) { return $workflow_can_email; } $is_allowed = true; $sender_usr_id = User::getUserIDByEmail($sender_email, true); if (empty($sender_usr_id)) { if (CRM::hasCustomerIntegration($prj_id)) { // check for a customer contact with several email addresses $crm = CRM::getInstance($prj_id); try { $contract = $crm->getContract(Issue::getContractID($issue_id)); $contact_emails = array_keys($contract->getContactEmailAssocList()); $contact_emails = array_map(function ($s) { return strtolower($s); }, $contact_emails); } catch (CRMException $e) { $contact_emails = array(); } if (!in_array(strtolower($sender_email), $contact_emails) && !Authorized_Replier::isAuthorizedReplier($issue_id, $sender_email)) { $is_allowed = false; } } else { if (!Authorized_Replier::isAuthorizedReplier($issue_id, $sender_email)) { $is_allowed = false; } } } else { // check if this user is not a customer and // also not in the assignment list for the current issue and // also not in the authorized repliers list // also not the reporter $details = Issue::getDetails($issue_id); if ($sender_usr_id == $details['iss_usr_id']) { $is_allowed = true; } elseif (User::isPartner($sender_usr_id) && in_array(User::getPartnerID($sender_usr_id), Partner::getPartnerCodesByIssue($issue_id))) { $is_allowed = true; } elseif (!Issue::canAccess($issue_id, $sender_usr_id) && !Authorized_Replier::isAuthorizedReplier($issue_id, $sender_email)) { $is_allowed = false; } elseif (!Authorized_Replier::isAuthorizedReplier($issue_id, $sender_email) && !Issue::isAssignedToUser($issue_id, $sender_usr_id) && User::getRoleByUser($sender_usr_id, Issue::getProjectID($issue_id)) != User::getRoleID('Customer')) { $is_allowed = false; } } return $is_allowed; }
/** * Processes the template and assign common variables automatically. * @return $this */ private function processTemplate() { $core = array('rel_url' => APP_RELATIVE_URL, 'base_url' => APP_BASE_URL, 'app_title' => APP_NAME, 'app_version' => APP_VERSION, 'app_setup' => Setup::load(), 'messages' => Misc::getMessages(), 'roles' => User::getAssocRoleIDs(), 'auth_backend' => APP_AUTH_BACKEND, 'current_url' => $_SERVER['PHP_SELF']); // If VCS version is present "Eventum 2.3.3-148-g78b3368", link ref to github $vcsVersion = self::getVcsVersion(); if ($vcsVersion) { $link = "https://github.com/eventum/eventum/commit/{$vcsVersion}"; $core['application_version_link'] = $link; // append VCS version if not yet there if (!preg_match('/-g[0-9a-f]+$/', APP_VERSION)) { $core['app_version'] = "v{$core['app_version']}-g{$vcsVersion}"; } } $usr_id = Auth::getUserID(); if ($usr_id) { $core['user'] = User::getDetails($usr_id); $prj_id = Auth::getCurrentProject(); $setup = Setup::load(); if (!empty($prj_id)) { $role_id = User::getRoleByUser($usr_id, $prj_id); $has_crm = CRM::hasCustomerIntegration($prj_id); $core = $core + array('project_id' => $prj_id, 'project_name' => Auth::getCurrentProjectName(), 'has_crm' => $has_crm, 'current_role' => $role_id, 'current_role_name' => User::getRole($role_id), 'feature_access' => Access::getFeatureAccessArray($usr_id)); if ($has_crm) { $crm = CRM::getInstance($prj_id); $core['crm_template_path'] = $crm->getTemplatePath(); if ($role_id == User::getRoleID('Customer')) { try { $contact = $crm->getContact($core['user']['usr_customer_contact_id']); $core['allowed_customers'] = $contact->getCustomers(); $core['current_customer'] = $crm->getCustomer(Auth::getCurrentCustomerID(false)); } catch (CRMException $e) { } } } } $info = User::getDetails($usr_id); $raw_projects = Project::getAssocList(Auth::getUserID(), false, true); $active_projects = array(); foreach ($raw_projects as $prj_id => $prj_info) { if ($prj_info['status'] == 'archived') { $prj_info['prj_title'] .= ' ' . ev_gettext('(archived)'); } $active_projects[$prj_id] = $prj_info['prj_title']; } $core = $core + array('active_projects' => $active_projects, 'current_full_name' => $info['usr_full_name'], 'current_email' => $info['usr_email'], 'current_user_id' => $usr_id, 'current_user_datetime' => Date_Helper::getISO8601date('now', '', true), 'is_current_user_clocked_in' => User::isCLockedIn($usr_id), 'is_anon_user' => Auth::isAnonUser(), 'is_current_user_partner' => !empty($info['usr_par_code']), 'roles' => User::getAssocRoleIDs(), 'current_user_prefs' => Prefs::get(Auth::getUserID())); $this->assign('current_full_name', $core['user']['usr_full_name']); $this->assign('current_email', $core['user']['usr_email']); $this->assign('current_user_id', $usr_id); $this->assign('handle_clock_in', $setup['handle_clock_in'] == 'enabled'); $this->assign('is_current_user_clocked_in', User::isClockedIn($usr_id)); $this->assign('roles', User::getAssocRoleIDs()); } $this->assign('core', $core); return $this; }
/** * 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. * * @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 */ public static function checkAuthentication($cookie_name, $failed_url = null, $is_popup = false) { self::getAuthBackend()->checkAuthentication(); if ($cookie_name == null) { $cookie_name = APP_COOKIE; } if ($failed_url == null) { $failed_url = APP_RELATIVE_URL . 'index.php?err=5'; } $failed_url .= '&url=' . urlencode($_SERVER['REQUEST_URI']); if (!isset($_COOKIE[$cookie_name])) { if (APP_ANON_USER) { $anon_usr_id = User::getUserIDByEmail(APP_ANON_USER); $prj_id = reset(array_keys(Project::getAssocList($anon_usr_id))); self::createFakeCookie($anon_usr_id, $prj_id); self::createLoginCookie(APP_COOKIE, APP_ANON_USER, false); self::setCurrentProject($prj_id, true); Session::init($anon_usr_id); } else { // check for valid HTTP_BASIC params if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { if (Auth::isCorrectPassword($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { $usr_id = User::getUserIDByEmail($_SERVER['PHP_AUTH_USER'], true); $prj_id = reset(array_keys(Project::getAssocList($usr_id))); self::createFakeCookie($usr_id, $prj_id); self::createLoginCookie(APP_COOKIE, APP_ANON_USER); self::setCurrentProject($prj_id, true); } else { header('WWW-Authenticate: Basic realm="Eventum"'); header('HTTP/1.0 401 Unauthorized'); echo 'Login Failed'; return; } } else { self::redirect($failed_url, $is_popup); } } } $cookie = $_COOKIE[$cookie_name]; $cookie = unserialize(base64_decode($cookie)); if (!self::isValidCookie($cookie)) { self::removeCookie($cookie_name); self::redirect($failed_url, $is_popup); } if (self::isPendingUser($cookie['email'])) { self::removeCookie($cookie_name); self::redirect('index.php?err=9', $is_popup); } if (!self::isActiveUser($cookie['email'])) { self::removeCookie($cookie_name); self::redirect('index.php?err=7', $is_popup); } $usr_id = self::getUserID(); // check the session Session::verify($usr_id); if (!defined('SKIP_LANGUAGE_INIT')) { Language::setPreference(); } // check whether the project selection is set or not $prj_id = self::getCurrentProject(); if (empty($prj_id)) { // redirect to select project page self::redirect(APP_RELATIVE_URL . 'select_project.php?url=' . urlencode($_SERVER['REQUEST_URI']), $is_popup); } // check the expiration date for a 'Customer' type user $contact_id = User::getCustomerContactID($usr_id); if (!empty($contact_id) && CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); $crm->authenticateCustomer(); } // auto switch project if (isset($_GET['switch_prj_id'])) { self::setCurrentProject($_GET['switch_prj_id'], false); self::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 self::createLoginCookie($cookie_name, $cookie['email'], $cookie['permanent']); // renew the project cookie as well $prj_cookie = self::getCookieInfo(APP_PROJECT_COOKIE); self::setCurrentProject($prj_id, $prj_cookie['remember']); }
/** * Method to determine if user can access a particular issue * * @param integer $issue_id The ID of the issue. * @param integer $usr_id The ID of the user * @return boolean If the user can access the issue */ public static function canAccessIssue($issue_id, $usr_id) { static $access; if (empty($issue_id)) { return false; } if (isset($access[$issue_id . '-' . $usr_id])) { return $access[$issue_id . '-' . $usr_id]; } $details = Issue::getDetails($issue_id); if (empty($details)) { return true; } $usr_details = User::getDetails($usr_id); $usr_role = User::getRoleByUser($usr_id, $details['iss_prj_id']); $prj_id = $details['iss_prj_id']; $can_access_contract = false; if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); try { if (!empty($usr_details['usr_customer_contact_id']) && !empty($details['iss_customer_contract_id'])) { $contact = $crm->getContact($usr_details['usr_customer_contact_id']); $can_access_contract = $contact->canAccessContract($crm->getContract($details['iss_customer_contract_id'])); } } catch (CRMException $e) { // TODOCRM: Log exception? } } if (empty($usr_role)) { // check if they are even allowed to access the project $return = false; } elseif (CRM::hasCustomerIntegration($details['iss_prj_id']) && $usr_role == User::getRoleID('Customer') && $can_access_contract === false) { // check customer permissions $return = false; } elseif (!empty($usr_details['usr_par_code']) && !Partner::isPartnerEnabledForIssue($usr_details['usr_par_code'], $issue_id)) { // check if the user is a partner $return = false; } elseif ($details['iss_private'] == 1) { // check if the issue is even private // check role, reporter, assignment and group if ($usr_role > User::getRoleID('Developer')) { $return = true; } elseif ($details['iss_usr_id'] == $usr_id) { $return = true; } elseif (Issue::isAssignedToUser($issue_id, $usr_id)) { $return = true; } elseif (!empty($details['iss_grp_id']) && !empty($usr_details['usr_grp_id']) && $details['iss_grp_id'] == $usr_details['usr_grp_id']) { $return = true; } elseif (Authorized_Replier::isUserAuthorizedReplier($issue_id, $usr_id)) { $return = true; } else { $return = false; } } elseif (Auth::getCurrentRole() == User::getRoleID('Reporter') && Project::getSegregateReporters($prj_id) && $details['iss_usr_id'] != $usr_id && !Authorized_Replier::isUserAuthorizedReplier($issue_id, $usr_id)) { return false; } else { $return = true; } $access[$issue_id . '-' . $usr_id] = $return; return $return; }
/** * @param int $issue_id * @param bool $redeemed_only * @return array * @access protected */ public function getIncidentTypes($issue_id, $redeemed_only) { $prj_id = Issue::getProjectID($issue_id); AuthCookie::setProjectCookie($prj_id); // FIXME: $customer_id unused $customer_id = Issue::getCustomerID($issue_id); if (!CRM::hasCustomerIntegration($prj_id)) { // no customer integration throw new RemoteApiException("No customer integration for issue #{$issue_id}"); } $crm = CRM::getInstance($prj_id); // FIXME: $all_types unused $all_types = $crm->getIncidentTypes(); $contract = $crm->getContract(Issue::getContractID($issue_id)); if (!$contract->hasPerIncident()) { // check if is per incident contract throw new RemoteApiException("Customer for issue #{$issue_id} does not have a per-incident contract"); } $incidents = $contract->getIncidents(); foreach ($incidents as $type_id => $type_details) { $is_redeemed = $contract->isRedeemedIncident($issue_id, $type_id); if ($redeemed_only && !$is_redeemed || !$redeemed_only && $is_redeemed) { unset($incidents[$type_id]); } } return $incidents; }
/** * Returns data for the custom fields report, based on the field and options passed in. * * @param integer $fld_id The id of the custom field. * @param array $cfo_ids An array of option ids. * @param string $group_by How the data should be grouped. * @param string $start_date * @param string $end_date * @param boolean $list If the values should be listed out instead of just counted. * @param string $interval The interval values should be grouped over time, empty (none) by default. * @param integer $assignee The assignee the issue should belong to. * @return array An array of data. */ public static function getCustomFieldReport($fld_id, $cfo_ids, $group_by = 'issue', $start_date = null, $end_date = null, $list = false, $interval = null, $assignee = null) { $prj_id = Auth::getCurrentProject(); $fld_id = (int) $fld_id; // get field values $options = Custom_Field::getOptions($fld_id, $cfo_ids); if ($group_by == 'customer') { $group_by_field = 'iss_customer_id'; } else { $group_by_field = 'iss_id'; } if ($assignee == -1) { $assignee = null; } $label_field = ''; $interval_group_by_field = ''; switch ($interval) { case 'day': $label_field = "CONCAT(YEAR(iss_created_date), '-', MONTH(iss_created_date), '-', DAY(iss_created_date))"; $interval_group_by_field = 'CONCAT(YEAR(iss_created_date), MONTH(iss_created_date), DAY(iss_created_date))'; break; case 'week': $label_field = "CONCAT(YEAR(iss_created_date), '/', WEEK(iss_created_date))"; $interval_group_by_field = 'WEEK(iss_created_date)'; break; case 'month': $label_field = "CONCAT(YEAR(iss_created_date), '/', MONTH(iss_created_date))"; $interval_group_by_field = 'MONTH(iss_created_date)'; break; case 'year': $label_field = 'YEAR(iss_created_date)'; $interval_group_by_field = 'YEAR(iss_created_date)'; break; } if ($list == true) { $params = array(); $sql = "SELECT\n DISTINCT({$group_by_field}),\n iss_id,\n iss_summary,\n iss_customer_id,\n count(DISTINCT(iss_id)) as row_count,\n iss_private,\n fld_id"; if ($label_field) { $sql .= ",\n {$label_field} as interval_label"; } $sql .= ' FROM {{%custom_field}},'; if (count($options) > 0) { $sql .= ' {{%custom_field_option}},'; } $sql .= ' {{%issue_custom_field}}, {{%issue}}, {{%issue_user}} WHERE fld_id = icf_fld_id AND'; if (count($options) > 0) { $sql .= ' cfo_id = icf_value AND'; } $sql .= ' icf_iss_id = iss_id AND isu_iss_id = iss_id AND icf_fld_id = ?'; $params[] = $fld_id; if (count($options) > 0) { $ids = array_keys($options); $list = DB_Helper::buildList($ids); $sql .= " AND cfo_id IN({$list})"; $params = array_merge($params, $ids); } if ($start_date && $end_date) { $sql .= " AND\niss_created_date BETWEEN ? AND ?"; $params[] = $start_date; $params[] = $end_date; } if ($assignee) { $sql .= " AND\nisu_usr_id = ?"; $params[] = $assignee; } $sql .= "\n GROUP BY\n {$group_by_field}\n ORDER BY"; if ($label_field) { $sql .= "\n {$label_field} DESC,"; } $sql .= ' row_count DESC'; try { $res = DB_Helper::getInstance()->getAll($sql, $params); } catch (DbException $e) { return array(); } if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); $crm->processListIssuesResult($res); if ($group_by == 'issue') { usort($res, function ($a, $b) { if ($a['customer_title'] < $b['customer_title']) { return -1; } elseif ($a['customer_title'] > $b['customer_title']) { return 1; } else { return 0; } }); } } foreach ($res as &$row) { $row['field_value'] = Custom_Field::getDisplayValue($row['iss_id'], $row['fld_id']); } return $res; } $data = array(); foreach ($options as $cfo_id => $value) { $params = array(); $stmt = 'SELECT'; if ($label_field != '') { $stmt .= "\n {$label_field} as label,"; } $stmt .= "\n COUNT(DISTINCT {$group_by_field})\n FROM\n {{%issue_custom_field}},\n {{%issue}},\n {{%issue_user}}\n WHERE\n icf_iss_id = iss_id AND\n isu_iss_id = iss_id AND\n icf_fld_id = ? AND\n icf_value = ?"; $params = array($fld_id, $cfo_id); if ($start_date && $end_date) { $stmt .= " AND\niss_created_date BETWEEN ? AND ?"; $params[] = $start_date; $params[] = $end_date; } if ($assignee) { $stmt .= " AND\nisu_usr_id = ?"; $params[] = $assignee; } if ($interval_group_by_field != '') { $stmt .= "\n GROUP BY\n {$interval_group_by_field}\n ORDER BY\n {$label_field} ASC"; try { $res = DB_Helper::getInstance()->fetchAssoc($stmt, $params); } catch (DbException $e) { return array(); } } else { try { $res = DB_Helper::getInstance()->getOne($stmt, $params); } catch (DbException $e) { return array(); } } $data[$value] = $res; } // include count of all other values (used in pie chart) $list = DB_Helper::buildList($cfo_ids); $stmt = "SELECT\n COUNT(DISTINCT {$group_by_field})\n FROM\n {{%custom_field_option}},\n {{%issue_custom_field}},\n {{%issue}}\n WHERE\n cfo_id = icf_value AND\n icf_iss_id = iss_id AND\n cfo_id NOT IN({$list}) AND\n icf_fld_id = ?\n "; $params = $cfo_ids; $params[] = $fld_id; try { $res = DB_Helper::getInstance()->getOne($stmt, $params); } catch (DbException $e) { return array(); } $data['All Others'] = $res; return $data; }
// | Free Software Foundation, Inc. | // | 51 Franklin Street, Suite 330 | // | Boston, MA 02110-1301, USA. | // +----------------------------------------------------------------------+ // | Authors: João Prado Maia <*****@*****.**> | // +----------------------------------------------------------------------+ require_once dirname(__FILE__) . '/../../init.php'; $tpl = new Template_Helper(); $tpl->setTemplate('manage/issue_auto_creation.tpl.html'); Auth::checkAuthentication(APP_COOKIE); @($ema_id = $_POST['ema_id'] ? $_POST['ema_id'] : $_GET['ema_id']); $role_id = Auth::getCurrentRole(); if ($role_id < User::getRoleID('administrator')) { Misc::setMessage('Sorry, you are not allowed to access this page.', Misc::MSG_ERROR); $tpl->displayTemplate(); exit; } $prj_id = Email_Account::getProjectID($ema_id); if (@$_POST['cat'] == 'update') { @Email_Account::updateIssueAutoCreation($ema_id, $_POST['issue_auto_creation'], $_POST['options']); } // load the form fields $tpl->assign('info', Email_Account::getDetails($ema_id)); $tpl->assign('cats', Category::getAssocList($prj_id)); $tpl->assign('priorities', Priority::getList($prj_id)); $tpl->assign('users', Project::getUserAssocList($prj_id, 'active')); $tpl->assign('options', Email_Account::getIssueAutoCreationOptions($ema_id)); $tpl->assign('ema_id', $ema_id); $tpl->assign('prj_title', Project::getName($prj_id)); $tpl->assign('uses_customer_integration', CRM::hasCustomerIntegration($prj_id)); $tpl->displayTemplate();
/** * Method used to send an email notification to the sender of a * set of email messages that were manually converted into an * issue. * * @param integer $prj_id The project ID * @param integer $issue_id The issue ID * @param array $sup_ids The email IDs * @param bool|int $customer_id The customer ID * @return array The list of recipient emails */ public static function notifyEmailConvertedIntoIssue($prj_id, $issue_id, $sup_ids, $customer_id = false) { if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); return $crm->notifyEmailConvertedIntoIssue($issue_id, $sup_ids, $customer_id); } else { // build the list of recipients $recipients = array(); $recipient_emails = array(); foreach ($sup_ids as $sup_id) { $senders = Support::getSender(array($sup_id)); if (count($senders) > 0) { $sender_email = Mail_Helper::getEmailAddress($senders[0]); $recipients[$sup_id] = $senders[0]; $recipient_emails[] = $sender_email; } } if (!$recipients) { return false; } $data = Issue::getDetails($issue_id); foreach ($recipients as $sup_id => $recipient) { $recipient_usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($recipient)); // open text template $tpl = new Template_Helper(); $tpl->setTemplate('notifications/new_auto_created_issue.tpl.text'); $tpl->assign(array('data' => $data, 'sender_name' => Mail_Helper::getName($recipient), 'app_title' => Misc::getToolCaption(), 'recipient_name' => Mail_Helper::getName($recipient))); $email_details = Support::getEmailDetails(Email_Account::getAccountByEmail($sup_id), $sup_id); $tpl->assign(array('email' => array('date' => $email_details['sup_date'], 'from' => $email_details['sup_from'], 'subject' => $email_details['sup_subject']))); // change the current locale if (!empty($recipient_usr_id)) { Language::set(User::getLang($recipient_usr_id)); } else { Language::set(APP_DEFAULT_LOCALE); } $text_message = $tpl->getTemplateContents(); // send email (use PEAR's classes) $mail = new Mail_Helper(); $mail->setTextBody($text_message); $setup = $mail->getSMTPSettings(); $from = self::getFixedFromHeader($issue_id, $setup['from'], 'issue'); $mail->setHeaders(Mail_Helper::getBaseThreadingHeaders($issue_id)); // TRANSLATORS: %1 - issue_id, %2 - iss_summary $subject = ev_gettext('[#%1$s] Issue Created: %2$s', $issue_id, $data['iss_summary']); $mail->send($from, $recipient, $subject, 1, $issue_id, 'email_converted_to_issue'); } Language::restore(); return $recipient_emails; } }
/** * Converts a note to a draft or an email * * @param int $note_id The id of the note * @param string $target What the note should be converted too (email, etc) * @param bool $authorize_sender If $authorize_sender If the sender should be added to authorized senders list. * @return int */ public static function convertNote($note_id, $target, $authorize_sender = false) { $issue_id = self::getIssueID($note_id); $email_account_id = Email_Account::getEmailAccount(); $blocked_message = self::getBlockedMessage($note_id); $unknown_user = self::getUnknownUser($note_id); $structure = Mime_Helper::decode($blocked_message, true, true); $body = $structure->body; $sender_email = strtolower(Mail_Helper::getEmailAddress($structure->headers['from'])); $current_usr_id = Auth::getUserID(); if ($target == 'email') { if (Mime_Helper::hasAttachments($structure)) { $has_attachments = 1; } else { $has_attachments = 0; } list($blocked_message, $headers) = Mail_Helper::rewriteThreadingHeaders($issue_id, $blocked_message, @$structure->headers); $t = array('issue_id' => $issue_id, 'ema_id' => $email_account_id, 'message_id' => @$structure->headers['message-id'], 'date' => Date_Helper::getCurrentDateGMT(), 'from' => @$structure->headers['from'], 'to' => @$structure->headers['to'], 'cc' => @$structure->headers['cc'], 'subject' => @$structure->headers['subject'], 'body' => @$body, 'full_email' => @$blocked_message, 'has_attachment' => $has_attachments, 'headers' => $headers); // need to check for a possible customer association if (!empty($structure->headers['from'])) { $details = Email_Account::getDetails($email_account_id); // check from the associated project if we need to lookup any customers by this email address if (CRM::hasCustomerIntegration($details['ema_prj_id'])) { $crm = CRM::getInstance($details['ema_prj_id']); // check for any customer contact association try { $contact = $crm->getContactByEmail($sender_email); $issue_contract = $crm->getContract(Issue::getContractID($issue_id)); if ($contact->canAccessContract($issue_contract)) { $t['customer_id'] = $issue_contract->getCustomerID(); } } catch (CRMException $e) { } } } if (empty($t['customer_id'])) { $update_type = 'staff response'; $t['customer_id'] = null; } else { $update_type = 'customer action'; } $res = Support::insertEmail($t, $structure, $sup_id); if ($res != -1) { Support::extractAttachments($issue_id, $structure); // notifications about new emails are always external $internal_only = false; // special case when emails are bounced back, so we don't want to notify the customer about those if (Notification::isBounceMessage($sender_email)) { $internal_only = true; } Notification::notifyNewEmail($current_usr_id, $issue_id, $t, $internal_only, false, '', $sup_id); Issue::markAsUpdated($issue_id, $update_type); self::remove($note_id, false); History::add($issue_id, $current_usr_id, 'note_converted_email', 'Note converted to e-mail (from: {from}) by {user}', array('from' => @$structure->headers['from'], 'user' => User::getFullName($current_usr_id))); // now add sender as an authorized replier if ($authorize_sender) { Authorized_Replier::manualInsert($issue_id, @$structure->headers['from']); } } return $res; } // save message as a draft $res = Draft::saveEmail($issue_id, $structure->headers['to'], $structure->headers['cc'], $structure->headers['subject'], $body, false, $unknown_user); // remove the note, if the draft was created successfully if ($res) { self::remove($note_id, false); $usr_id = $current_usr_id; History::add($issue_id, $usr_id, 'note_converted_draft', 'Note converted to draft (from: {from}) by {user}', array('from' => @$structure->headers['from'], 'user' => User::getFullName($current_usr_id))); } return $res; }
$time_spent = (int) $_POST['time_spent']; $summary = 'Time entry inserted when closing issue.'; Time_Tracking::addTimeEntry($iss_id, $ttc_id, $time_spent, $date, $summary); } if (CRM::hasCustomerIntegration($prj_id) && isset($details['contract'])) { $crm = CRM::getInstance($prj_id); $contract = $details['contract']; if ($contract->hasPerIncident()) { $contract->updateRedeemedIncidents($issue_id, @$_REQUEST['redeem']); } } $tpl->assign('close_result', $res); if ($res == 1) { Misc::setMessage(ev_gettext('Thank you, the issue was closed successfully')); Misc::displayNotifiedUsers(Notification::getLastNotifiedAddresses($issue_id)); Auth::redirect(APP_RELATIVE_URL . 'view.php?id=' . $issue_id); } } $tpl->assign(array('statuses' => Status::getClosedAssocList($prj_id), 'resolutions' => Resolution::getAssocList(), 'time_categories' => Time_Tracking::getAssocCategories($prj_id), 'notify_list' => Notification::getLastNotifiedAddresses($issue_id), 'custom_fields' => Custom_Field::getListByIssue($prj_id, $issue_id, $usr_id, 'close_form'), 'issue_id' => $issue_id)); if (CRM::hasCustomerIntegration($prj_id) && isset($details['contract'])) { $crm = CRM::getInstance($prj_id); $contract = $details['contract']; if ($contract->hasPerIncident()) { $details = Issue::getDetails($issue_id); $tpl->assign(array('redeemed' => $contract->getRedeemedIncidentDetails($issue_id), 'incident_details' => $details['customer']['incident_details'])); } } $usr_id = Auth::getUserID(); $user_prefs = Prefs::get($usr_id); $tpl->assign('current_user_prefs', $user_prefs); $tpl->displayTemplate();
// | Authors: João Prado Maia <*****@*****.**> | // +----------------------------------------------------------------------+ require_once dirname(__FILE__) . '/../../init.php'; $tpl = new Template_Helper(); $tpl->setTemplate('manage/field_display.tpl.html'); Auth::checkAuthentication(APP_COOKIE); $tpl->assign('type', 'field_display'); $prj_id = @$_GET['prj_id']; $role_id = Auth::getCurrentRole(); if ($role_id < User::ROLE_MANAGER) { Misc::setMessage(ev_gettext('Sorry, you are not allowed to access this page.'), Misc::MSG_ERROR); $tpl->displayTemplate(); exit; } if (count(@$_POST['fields']) > 0) { $res = Project::updateFieldDisplaySettings($prj_id, $_POST['fields']); $tpl->assign('result', $res); Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the information was updated successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to update the information.'), Misc::MSG_ERROR))); } $fields = Project::getDisplayFields(); $excluded_roles = array('viewer'); if (!CRM::hasCustomerIntegration($prj_id)) { $excluded_roles[] = 'customer'; } $user_roles = User::getRoles($excluded_roles); $user_roles[9] = 'Never Display'; $tpl->assign('prj_id', $prj_id); $tpl->assign('fields', $fields); $tpl->assign('user_roles', $user_roles); $tpl->assign('display_settings', Project::getFieldDisplaySettings($prj_id)); $tpl->displayTemplate();
/** * Routes an email to the correct issue. * * @param string $full_message The full email message, including headers * @return mixed true or array(ERROR_CODE, ERROR_STRING) in case of failure */ public static function route_emails($full_message) { // need some validation here if (empty($full_message)) { return array(self::EX_NOINPUT, ev_gettext('Error: The email message was empty') . ".\n"); } // save the full message for logging purposes Support::saveRoutedEmail($full_message); // check if the email routing interface is even supposed to be enabled $setup = Setup::get(); if ($setup['email_routing']['status'] != 'enabled') { return array(self::EX_CONFIG, ev_gettext('Error: The email routing interface is disabled.') . "\n"); } if (empty($setup['email_routing']['address_prefix'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address prefix.') . "\n"); } if (empty($setup['email_routing']['address_host'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address domain.') . "\n"); } // associate routed emails to the internal system account $sys_account = User::getNameEmail(APP_SYSTEM_USER_ID); if (empty($sys_account['usr_email'])) { return array(self::EX_CONFIG, ev_gettext('Error: The associated user for the email routing interface needs to be set.') . "\n"); } unset($sys_account); // join the Content-Type line (for easier parsing?) if (preg_match('/^boundary=/m', $full_message)) { $pattern = "#(Content-Type: multipart/.+); ?\r?\n(boundary=.*)\$#im"; $replacement = '$1; $2'; $full_message = preg_replace($pattern, $replacement, $full_message); } // remove the reply-to: header if (preg_match('/^reply-to:.*/im', $full_message)) { $full_message = preg_replace("/^(reply-to:).*\n/im", '', $full_message, 1); } AuthCookie::setAuthCookie(APP_SYSTEM_USER_ID); $structure = Mime_Helper::decode($full_message, true, true); // find which issue ID this email refers to if (isset($structure->headers['to'])) { $issue_id = self::getMatchingIssueIDs($structure->headers['to'], 'email'); } // we need to try the Cc header as well if (empty($issue_id) and isset($structure->headers['cc'])) { $issue_id = self::getMatchingIssueIDs($structure->headers['cc'], 'email'); } if (empty($issue_id)) { return array(self::EX_DATAERR, ev_gettext('Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.') . "\n"); } $issue_prj_id = Issue::getProjectID($issue_id); if (empty($issue_prj_id)) { return array(self::EX_DATAERR, ev_gettext('Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.') . "\n"); } $email_account_id = Email_Account::getEmailAccount($issue_prj_id); if (empty($email_account_id)) { return array(self::EX_CONFIG, ev_gettext('Error: Please provide the email account ID.') . "\n"); } $body = $structure->body; // hack for clients that set more then one from header if (is_array($structure->headers['from'])) { $structure->headers['from'] = $structure->headers['from'][0]; } // associate the email to the issue $parts = array(); Mime_Helper::parse_output($structure, $parts); // get the sender's email address $sender_email = strtolower(Mail_Helper::getEmailAddress($structure->headers['from'])); // strip out the warning message sent to staff users if ($setup['email_routing']['status'] == 'enabled' && $setup['email_routing']['warning']['status'] == 'enabled') { $full_message = Mail_Helper::stripWarningMessage($full_message); $body = Mail_Helper::stripWarningMessage($body); } $prj_id = Issue::getProjectID($issue_id); AuthCookie::setAuthCookie(APP_SYSTEM_USER_ID); AuthCookie::setProjectCookie($prj_id); if (Mime_Helper::hasAttachments($structure)) { $has_attachments = 1; } else { $has_attachments = 0; } // remove certain CC addresses if (!empty($structure->headers['cc']) && $setup['smtp']['save_outgoing_email'] == 'yes') { $ccs = explode(',', @$structure->headers['cc']); foreach ($ccs as $i => $address) { if (Mail_Helper::getEmailAddress($address) == $setup['smtp']['save_address']) { unset($ccs[$i]); } } $structure->headers['cc'] = implode(', ', $ccs); } // Remove excess Re's $structure->headers['subject'] = Mail_Helper::removeExcessRe(@$structure->headers['subject'], true); $t = array('issue_id' => $issue_id, 'ema_id' => $email_account_id, 'message_id' => @$structure->headers['message-id'], 'date' => Date_Helper::getCurrentDateGMT(), 'from' => @$structure->headers['from'], 'to' => @$structure->headers['to'], 'cc' => @$structure->headers['cc'], 'subject' => @$structure->headers['subject'], 'body' => @$body, 'full_email' => @$full_message, 'has_attachment' => $has_attachments, 'headers' => @$structure->headers); // automatically associate this incoming email with a customer if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); if (!empty($structure->headers['from'])) { try { $contact = $crm->getContactByEmail($sender_email); $issue_contract = $crm->getContract(Issue::getContractID($issue_id)); if ($contact->canAccessContract($issue_contract)) { $t['customer_id'] = $issue_contract->getCustomerID(); } } catch (CRMException $e) { } } } if (empty($t['customer_id'])) { $t['customer_id'] = null; } if (Support::blockEmailIfNeeded($t)) { return true; } // re-write Threading headers if needed list($t['full_email'], $t['headers']) = Mail_Helper::rewriteThreadingHeaders($t['issue_id'], $t['full_email'], $t['headers'], 'email'); $res = Support::insertEmail($t, $structure, $sup_id); if ($res != -1) { Support::extractAttachments($issue_id, $structure); // notifications about new emails are always external $internal_only = false; $assignee_only = false; // special case when emails are bounced back, so we don't want a notification to customers about those if (Notification::isBounceMessage($sender_email)) { // broadcast this email only to the assignees for this issue $internal_only = true; $assignee_only = true; } Notification::notifyNewEmail(Auth::getUserID(), $issue_id, $t, $internal_only, $assignee_only, '', $sup_id); // try to get usr_id of sender, if not, use system account $usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($structure->headers['from'])); if (!$usr_id) { $usr_id = APP_SYSTEM_USER_ID; } // mark this issue as updated if (!empty($t['customer_id']) && $t['customer_id'] != null) { Issue::markAsUpdated($issue_id, 'customer action'); } else { if (!empty($usr_id) && $usr_id != APP_SYSTEM_USER_ID && User::getRoleByUser($usr_id, $prj_id) > User::ROLE_CUSTOMER) { Issue::markAsUpdated($issue_id, 'staff response'); } else { Issue::markAsUpdated($issue_id, 'user response'); } } // log routed email History::add($issue_id, $usr_id, 'email_routed', 'Email routed from {from}', array('from' => $structure->headers['from'])); } return true; }