/** * Adds an email to the outgoing mail queue. * * @param string $recipient The recipient of this email * @param array $headers The list of headers that should be sent with this email * @param string $body The body of the message * @param integer $save_email_copy Whether to send a copy of this email to a configurable address or not (eventum_sent@) * @param integer $issue_id The ID of the issue. If false, email will not be associated with issue. * @param string $type The type of message this is. * @param integer $sender_usr_id The id of the user sending this email. * @param integer $type_id The ID of the event that triggered this notification (issue_id, sup_id, not_id, etc) * @return true, or a PEAR_Error object */ public static function add($recipient, $headers, $body, $save_email_copy = 0, $issue_id = false, $type = '', $sender_usr_id = false, $type_id = false) { Workflow::modifyMailQueue(Auth::getCurrentProject(false), $recipient, $headers, $body, $issue_id, $type, $sender_usr_id, $type_id); // avoid sending emails out to users with inactive status $recipient_email = Mail_Helper::getEmailAddress($recipient); $usr_id = User::getUserIDByEmail($recipient_email); if (!empty($usr_id)) { $user_status = User::getStatusByEmail($recipient_email); // if user is not set to an active status, then silently ignore if (!User::isActiveStatus($user_status) && !User::isPendingStatus($user_status)) { return false; } } $to_usr_id = User::getUserIDByEmail($recipient_email); $recipient = Mail_Helper::fixAddressQuoting($recipient); $reminder_addresses = Reminder::_getReminderAlertAddresses(); // add specialized headers if (!empty($issue_id) && (!empty($to_usr_id) && User::getRoleByUser($to_usr_id, Issue::getProjectID($issue_id)) != User::getRoleID('Customer')) || @in_array(Mail_Helper::getEmailAddress($recipient), $reminder_addresses)) { $headers += Mail_Helper::getSpecializedHeaders($issue_id, $type, $headers, $sender_usr_id); } // try to prevent triggering absence auto responders $headers['precedence'] = 'bulk'; // the 'classic' way, works with e.g. the unix 'vacation' tool $headers['Auto-submitted'] = 'auto-generated'; // the RFC 3834 way if (empty($issue_id)) { $issue_id = 'null'; } // if the Date: header is missing, add it. if (empty($headers['Date'])) { $headers['Date'] = Mime_Helper::encode(date('D, j M Y H:i:s O')); } if (!empty($headers['To'])) { $headers['To'] = Mail_Helper::fixAddressQuoting($headers['To']); } // encode headers and add special mime headers $headers = Mime_Helper::encodeHeaders($headers); $res = Mail_Helper::prepareHeaders($headers); if (Misc::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); return $res; } // convert array of headers into text headers list(, $text_headers) = $res; $params = array('maq_save_copy' => $save_email_copy, 'maq_queued_date' => Date_Helper::getCurrentDateGMT(), 'maq_sender_ip_address' => !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'maq_recipient' => $recipient, 'maq_headers' => $text_headers, 'maq_body' => $body, 'maq_iss_id' => $issue_id, 'maq_subject' => $headers['Subject'], 'maq_type' => $type); if ($sender_usr_id) { $params['maq_usr_id'] = $sender_usr_id; } if ($type_id) { $params['maq_type_id'] = $type_id; } $stmt = 'INSERT INTO {{%mail_queue}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return $res; } return true; }
/** * Method used to add a customized warning message to the body * of outgoing emails. * * @param integer $issue_id The issue ID * @param string $to The recipient of the message * @param string $body The body of the message * @param array $headers The headers of the message * @return string The body of the message with the warning message, if appropriate */ public static function addWarningMessage($issue_id, $to, $body, $headers) { $setup = Setup::load(); if (@$setup['email_routing']['status'] == 'enabled' && $setup['email_routing']['warning']['status'] == 'enabled') { // check if the recipient can send emails to the customer $recipient_email = self::getEmailAddress($to); $recipient_usr_id = User::getUserIDByEmail($recipient_email); // don't add the warning message if the recipient is an unknown email address if (empty($recipient_usr_id)) { return $body; } else { // don't add anything if the recipient is a known customer contact $recipient_role_id = User::getRoleByUser($recipient_usr_id, Issue::getProjectID($issue_id)); if ($recipient_role_id == User::getRoleID('Customer')) { return $body; } else { if (!Support::isAllowedToEmail($issue_id, $recipient_email)) { $warning = self::getWarningMessage('blocked'); } else { $warning = self::getWarningMessage('allowed'); } if (@$headers['Content-Transfer-Encoding'] == 'base64') { return base64_encode($warning . "\n\n" . trim(base64_decode($body))); } else { return $warning . "\n\n" . $body; } } } } else { return $body; } }
public static function canAccessReports($usr_id) { $prj_id = Auth::getCurrentProject(); if (User::isPartner($usr_id)) { $partner = Partner::canUserAccessFeature($usr_id, 'reports'); if (is_bool($partner)) { return $partner; } } if (User::getRoleByUser($usr_id, $prj_id) > User::getRoleID('Customer')) { return true; } return false; }
/** * Method to update the details of a specific issue. * * @param integer $issue_id The issue ID * @return integer 1 if the update worked, -1 or -2 otherwise */ public static function update($issue_id) { $issue_id = (int) $issue_id; $usr_id = Auth::getUserID(); $prj_id = self::getProjectID($issue_id); $workflow = Workflow::preIssueUpdated($prj_id, $issue_id, $usr_id, $_POST); if ($workflow !== true) { return $workflow; } // get all of the 'current' information of this issue $current = self::getDetails($issue_id); $associated_issues = isset($_POST['associated_issues']) ? explode(',', $_POST['associated_issues']) : array(); self::updateAssociatedIssuesRelations($issue_id, $associated_issues); $assignments_changed = false; if (@$_POST['keep_assignments'] == 'no') { // only change the issue-user associations if there really were any changes $old_assignees = array_merge($current['assigned_users'], $current['assigned_inactive_users']); if (!empty($_POST['assignments'])) { $new_assignees = @$_POST['assignments']; } else { $new_assignees = array(); } $assignment_notifications = array(); // remove people from the assignment list, if appropriate foreach ($old_assignees as $assignee) { if (!in_array($assignee, $new_assignees)) { self::deleteUserAssociation($issue_id, $assignee); $assignments_changed = true; } } // add people to the assignment list, if appropriate foreach ($new_assignees as $assignee) { if (!in_array($assignee, $old_assignees)) { self::addUserAssociation($usr_id, $issue_id, $assignee); Notification::subscribeUser($usr_id, $issue_id, $assignee, Notification::getDefaultActions($issue_id, User::getEmail($assignee), 'issue_update'), true); $assignment_notifications[] = $assignee; $assignments_changed = true; } } if (count($assignment_notifications) > 0) { Notification::notifyNewAssignment($assignment_notifications, $issue_id); } } if (empty($_POST['estimated_dev_time'])) { $_POST['estimated_dev_time'] = 0; } $params = array('iss_updated_date' => Date_Helper::getCurrentDateGMT(), 'iss_last_public_action_date' => Date_Helper::getCurrentDateGMT(), 'iss_last_public_action_type' => 'updated', 'iss_sta_id' => $_POST['status'], 'iss_summary' => $_POST['summary'], 'iss_description' => $_POST['description']); if (isset($_POST['release'])) { $params['iss_pre_id'] = $_POST['release']; } if (isset($_POST['percentage_complete'])) { $params['iss_percent_complete'] = $_POST['percentage_complete']; } if (isset($_POST['group'])) { $params['iss_grp_id'] = $_POST['group']; } if (isset($_POST['estimated_dev_time'])) { $params['iss_dev_time'] = $_POST['estimated_dev_time']; } if (isset($_POST['trigger_reminders'])) { $params['iss_trigger_reminders'] = $_POST['trigger_reminders']; } if (isset($_POST['resolution'])) { $params['iss_res_id'] = $_POST['resolution']; } if (!empty($_POST['category'])) { $params['iss_prc_id'] = $_POST['category']; } if (@$_POST['keep'] == 'no') { $params['iss_pre_id'] = $_POST['release']; } if (!empty($_POST['expected_resolution_date'])) { $params['iss_expected_resolution_date'] = $_POST['expected_resolution_date']; } else { $params['iss_expected_resolution_date'] = null; } if (isset($_POST['private'])) { $params['iss_private'] = $_POST['private']; } if (isset($_POST['priority'])) { $params['iss_pri_id'] = $_POST['priority']; } if (isset($_POST['severity'])) { $params['iss_sev_id'] = $_POST['severity']; } if (isset($_POST['scheduled_release'])) { $params['iss_pre_id'] = $_POST['scheduled_release']; } $stmt = 'UPDATE {{%issue}} SET ' . DB_Helper::buildSet($params) . ' WHERE iss_id=?'; $params[] = $issue_id; try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } // change product if (isset($_POST['product'])) { $product_changes = Product::updateProductsByIssue($issue_id, $_POST['product'], $_POST['product_version']); } // add change to the history (only for changes on specific fields?) $updated_fields = array(); if ($current['iss_expected_resolution_date'] != $_POST['expected_resolution_date']) { $updated_fields['Expected Resolution Date'] = History::formatChanges($current['iss_expected_resolution_date'], $_POST['expected_resolution_date']); } if (isset($_POST['category']) && $current['iss_prc_id'] != $_POST['category']) { $updated_fields['Category'] = History::formatChanges(Category::getTitle($current['iss_prc_id']), Category::getTitle($_POST['category'])); } if (isset($_POST['release']) && $current['iss_pre_id'] != $_POST['release']) { $updated_fields['Release'] = History::formatChanges(Release::getTitle($current['iss_pre_id']), Release::getTitle($_POST['release'])); } if (isset($_POST['priority']) && $current['iss_pri_id'] != $_POST['priority']) { $updated_fields['Priority'] = History::formatChanges(Priority::getTitle($current['iss_pri_id']), Priority::getTitle($_POST['priority'])); Workflow::handlePriorityChange($prj_id, $issue_id, $usr_id, $current, $_POST); } if (isset($_POST['severity']) && $current['iss_sev_id'] != $_POST['severity']) { $updated_fields['Severity'] = History::formatChanges(Severity::getTitle($current['iss_sev_id']), Severity::getTitle($_POST['severity'])); Workflow::handleSeverityChange($prj_id, $issue_id, $usr_id, $current, $_POST); } if (isset($_POST['scheduled_release']) && $current['iss_pre_id'] != $_POST['scheduled_release']) { $updated_fields['Scheduled Release'] = History::formatChanges(Release::getTitle($current['iss_pre_id']), Release::getTitle($_POST['scheduled_release'])); } if (isset($_POST['status']) && $current['iss_sta_id'] != $_POST['status']) { // clear out the last-triggered-reminder flag when changing the status of an issue Reminder_Action::clearLastTriggered($issue_id); // if old status was closed and new status is not, clear closed data from issue. $old_status_details = Status::getDetails($current['iss_sta_id']); if ($old_status_details['sta_is_closed'] == 1) { $new_status_details = Status::getDetails($_POST['status']); if ($new_status_details['sta_is_closed'] != 1) { self::clearClosed($issue_id); } } $updated_fields['Status'] = History::formatChanges(Status::getStatusTitle($current['iss_sta_id']), Status::getStatusTitle($_POST['status'])); } if (isset($_POST['resolution']) && $current['iss_res_id'] != $_POST['resolution']) { $updated_fields['Resolution'] = History::formatChanges(Resolution::getTitle($current['iss_res_id']), Resolution::getTitle($_POST['resolution'])); } if (isset($_POST['estimated_dev_time']) && $current['iss_dev_time'] != $_POST['estimated_dev_time']) { $updated_fields['Estimated Dev. Time'] = History::formatChanges(Misc::getFormattedTime($current['iss_dev_time'] * 60), Misc::getFormattedTime($_POST['estimated_dev_time'] * 60)); } if ($current['iss_summary'] != $_POST['summary']) { $updated_fields['Summary'] = ''; } if (isset($_POST['percentage_complete']) && $current['iss_original_percent_complete'] != $_POST['percentage_complete']) { $updated_fields['Percentage complete'] = History::formatChanges($current['iss_original_percent_complete'], $_POST['percentage_complete']); } if ($current['iss_original_description'] != $_POST['description']) { $updated_fields['Description'] = ''; } if (isset($_POST['private']) && $_POST['private'] != $current['iss_private']) { $updated_fields['Private'] = History::formatChanges(Misc::getBooleanDisplayValue($current['iss_private']), Misc::getBooleanDisplayValue($_POST['private'])); } if (isset($_POST['product']) && count($product_changes) > 0) { $updated_fields['Product'] = implode('; ', $product_changes); } if (isset($_POST['custom_fields']) && count($_POST['custom_fields']) > 0) { $updated_custom_fields = Custom_Field::updateValues($issue_id, $_POST['custom_fields']); } else { $updated_custom_fields = array(); } if (count($updated_fields) > 0) { // log the changes $changes = ''; $i = 0; foreach ($updated_fields as $key => $value) { if ($i > 0) { $changes .= '; '; } if ($key != 'Summary' && $key != 'Description') { $changes .= "{$key}: {$value}"; } else { $changes .= "{$key}"; } $i++; } History::add($issue_id, $usr_id, 'issue_updated', 'Issue updated ({changes}) by {user}', array('changes' => $changes, 'user' => User::getFullName($usr_id))); } if (count($updated_fields) > 0 || count($updated_custom_fields) > 0) { // send notifications for the issue being updated Notification::notifyIssueUpdated($issue_id, $current, $_POST, $updated_custom_fields); } // record group change as a separate change if (isset($_POST['group']) && $current['iss_grp_id'] != (int) $_POST['group']) { History::add($issue_id, $usr_id, 'group_changed', 'Group changed ({changes}) by {user}', array('changes' => History::formatChanges(Group::getName($current['iss_grp_id']), Group::getName($_POST['group'])), 'user' => User::getFullName($usr_id))); } // now update any duplicates, if any $update_dupe = array('Category', 'Release', 'Priority', 'Release', 'Resolution'); $intersect = array_intersect($update_dupe, array_keys($updated_fields)); if ($current['duplicates'] != '' && count($intersect) > 0) { self::updateDuplicates($issue_id); } // if there is customer integration, mark last customer action if (CRM::hasCustomerIntegration($prj_id) && User::getRoleByUser($usr_id, $prj_id) == User::ROLE_CUSTOMER) { self::recordLastCustomerAction($issue_id); } if ($assignments_changed) { // XXX: we may want to also send the email notification for those "new" assignees Workflow::handleAssignmentChange(self::getProjectID($issue_id), $issue_id, $usr_id, self::getDetails($issue_id), @$_POST['assignments'], false); } Workflow::handleIssueUpdated($prj_id, $issue_id, $usr_id, $current, $_POST); // Move issue to another project if (isset($_POST['move_issue']) and User::getRoleByUser($usr_id, $prj_id) >= User::ROLE_DEVELOPER) { $new_prj_id = (int) @$_POST['new_prj']; if ($prj_id != $new_prj_id && array_key_exists($new_prj_id, Project::getAssocList($usr_id))) { if (User::getRoleByUser($usr_id, $new_prj_id) >= User::ROLE_REPORTER) { $res = self::moveIssue($issue_id, $new_prj_id); if ($res == -1) { return $res; } } else { return -1; } } } return 1; }
/** * Called when an attempt is made to add a user or email address to the * notification list. * * @param integer $prj_id The project ID * @param integer $issue_id The ID of the issue. * @param integer $subscriber_usr_id The ID of the user to subscribe if this is a real user (false otherwise). * @param string $email The email address to subscribe to subscribe (if this is not a real user). * @param array $types The action types. * @return mixed An array of information or true to continue unchanged or false to prevent the user from being added. */ function handleSubscription($prj_id, $issue_id, &$subscriber_usr_id, &$email, &$actions) { if ($prj_id != 5) { if (User::getRoleByUser($subscriber_usr_id, $prj_id) >= User::getRoleID('Developer')) { return false; } } return true; }
/** * @param int $prj_id * @param string $field * @param string $value * @access protected * @return string */ public function lookupCustomer($prj_id, $field, $value) { $possible_fields = array('email', 'support', 'customer'); if (!in_array($field, $possible_fields)) { throw new RemoteApiException("Unknown field type '{$field}'"); } $usr_id = Auth::getUserID(); // only customers should be able to use this page $role_id = User::getRoleByUser($usr_id, $prj_id); if ($role_id < User::ROLE_DEVELOPER) { throw new RemoteApiException("You don't have the appropriate permissions to lookup customer information"); } $crm = CRM::getInstance($prj_id); if (!$crm) { throw new RemoteApiException("Customer Integration not enabled for project {$prj_id}"); } $res = $crm->lookup($field, $value, array()); return $res; }
/** * 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; }
/** * 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; }
/** * Method used to get the list of custom fields and custom field * values associated with a given issue ID. If usr_id is false method * defaults to current user. * * @access public * @param integer $prj_id The project ID * @param integer $iss_id The issue ID * @param integer $usr_id The ID of the user who is going to be viewing this list. * @return array The list of custom fields */ function getListByIssue($prj_id, $iss_id, $usr_id = false) { if ($usr_id == false) { $usr_id = Auth::getUserID(); } $usr_role = User::getRoleByUser($usr_id, $prj_id); if (empty($usr_role)) { $usr_role = 0; } $stmt = "SELECT\n fld_id,\n fld_title,\n fld_type,\n fld_report_form_required,\n fld_anonymous_form_required,\n icf_value,\n fld_min_role\n FROM\n (\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "custom_field,\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_custom_field\n )\n LEFT JOIN\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_custom_field\n ON\n pcf_fld_id=icf_fld_id AND\n icf_iss_id=" . Misc::escapeInteger($iss_id) . "\n WHERE\n pcf_fld_id=fld_id AND\n pcf_prj_id=" . Misc::escapeInteger($prj_id) . " AND\n fld_min_role <= " . $usr_role . "\n ORDER BY\n fld_rank ASC"; $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC); if (PEAR::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); return array(); } else { if (count($res) == 0) { return array(); } else { $fields = array(); for ($i = 0; $i < count($res); $i++) { if ($res[$i]['fld_type'] == 'text' || $res[$i]['fld_type'] == 'textarea' || $res[$i]['fld_type'] == 'date') { $fields[] = $res[$i]; } elseif ($res[$i]["fld_type"] == "combo") { $res[$i]["selected_cfo_id"] = $res[$i]["icf_value"]; $res[$i]["icf_value"] = Custom_Field::getOptionValue($res[$i]["fld_id"], $res[$i]["icf_value"]); $res[$i]["field_options"] = Custom_Field::getOptions($res[$i]["fld_id"]); $fields[] = $res[$i]; } elseif ($res[$i]['fld_type'] == 'multiple') { // check whether this field is already in the array $found = 0; for ($y = 0; $y < count($fields); $y++) { if ($fields[$y]['fld_id'] == $res[$i]['fld_id']) { $found = 1; $found_index = $y; } } if (!$found) { $res[$i]["selected_cfo_id"] = array($res[$i]["icf_value"]); $res[$i]["icf_value"] = Custom_Field::getOptionValue($res[$i]["fld_id"], $res[$i]["icf_value"]); $res[$i]["field_options"] = Custom_Field::getOptions($res[$i]["fld_id"]); $fields[] = $res[$i]; } else { $fields[$found_index]['icf_value'] .= ', ' . Custom_Field::getOptionValue($res[$i]["fld_id"], $res[$i]["icf_value"]); $fields[$found_index]['selected_cfo_id'][] = $res[$i]["icf_value"]; } } } foreach ($fields as $key => $field) { $backend = Custom_Field::getBackend($field['fld_id']); if (is_object($backend) && is_subclass_of($backend, "Dynamic_Custom_Field_Backend")) { $fields[$key]['dynamic_options'] = $backend->getStructuredData(); $fields[$key]['controlling_field_id'] = $backend->getControllingCustomFieldID(); $fields[$key]['controlling_field_name'] = $backend->getControllingCustomFieldName(); $fields[$key]['hide_when_no_options'] = $backend->hideWhenNoOptions(); // START ETEL MODIFIED $fields[$key]['showTransactionLookup'] = $backend->showTransactionLookup; // END ETEL MODIFIED } } return $fields; } } }
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(); } } }
if (!isset($issue_fields_display['percent_complete']) || $issue_fields_display['percent_complete'] != false) { $columns[0][] = array('title' => ev_gettext('Percentage Complete'), 'data' => (empty($details['iss_percent_complete']) ? 0 : $details['iss_percent_complete']) . '%', 'field' => 'percentage_complete'); } $columns[0][] = array('title' => ev_gettext('Reporter'), 'field' => 'reporter'); $products = Product::getAssocList(false); if (count($products) > 0) { $columns[0][] = array('title' => ev_gettext('Product'), 'field' => 'product'); $columns[0][] = array('title' => ev_gettext('Product Version'), 'field' => 'product_version'); } $columns[0][] = array('title' => ev_gettext('Assignment'), 'data' => $details['assignments'], 'field' => 'assignment'); $columns[1][] = array('title' => ev_gettext('Notification List'), 'field' => 'notification_list'); $columns[1][] = array('title' => ev_gettext('Submitted Date'), 'data' => $details['iss_created_date']); $columns[1][] = array('title' => ev_gettext('Last Updated Date'), 'data' => $details['iss_updated_date']); $columns[1][] = array('title' => ev_gettext('Associated Issues'), 'field' => 'associated_issues'); if (!isset($issue_fields_display['expected_resolution']) || $issue_fields_display['expected_resolution'] != false) { $columns[1][] = array('title' => ev_gettext('Expected Resolution Date'), 'field' => 'expected_resolution'); } if (!isset($issue_fields_display['estimated_dev_time']) || $issue_fields_display['estimated_dev_time'] != false) { $columns[1][] = array('title' => ev_gettext('Estimated Dev. Time'), 'data' => $details['iss_dev_time'] . empty($details['iss_dev_time']) ? '' : ' hours', 'field' => 'estimated_dev_time'); } if ($role_id > User::getRoleID('Customer')) { $columns[1][] = array('title' => ev_gettext('Duplicates'), 'field' => 'duplicates', 'title_bgcolor' => APP_INTERNAL_COLOR); $columns[1][] = array('title' => ev_gettext('Authorized Repliers'), 'field' => 'authorized_repliers', 'title_bgcolor' => APP_INTERNAL_COLOR); } $groups = Group::getAssocList($prj_id); if ($role_id > User::getRoleID('Customer') && count($groups) > 0) { $columns[1][] = array('title' => ev_gettext('Group'), 'data' => isset($details['group']) ? $details['group']['grp_name'] : '', 'title_bgcolor' => APP_INTERNAL_COLOR); } $tpl->assign(array('subscribers' => Notification::getSubscribers($issue_id), 'categories' => $categories, 'priorities' => $priorities, 'severities' => $severities, 'status' => $statuses, 'releases' => $releases, 'resolutions' => Resolution::getAssocList(), 'users' => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')), 'one_week_ts' => time() + 7 * Date_Helper::DAY, 'groups' => Group::getAssocList($prj_id), 'current_year' => date('Y'), 'products' => Product::getList(false), 'grid' => $columns)); $tpl->assign('usr_role_id', User::getRoleByUser($usr_id, $prj_id)); $tpl->displayTemplate();
/** * Adds a real user to the authorized repliers list. * * @access public * @param integer $issue_id The id of the issue. * @param integer $usr_id The id of the user. * @param boolean $add_history If this should be logged. */ function addUser($issue_id, $usr_id, $add_history = true) { // don't add customers to this list. They should already be able to send if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) == User::getRoleID("Customer")) { return -2; } $stmt = "INSERT INTO\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user_replier\n (\n iur_iss_id,\n iur_usr_id\n ) VALUES (\n " . Misc::escapeInteger($issue_id) . ",\n " . Misc::escapeInteger($usr_id) . "\n )"; $res = $GLOBALS["db_api"]->dbh->query($stmt); if (PEAR::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); return -1; } else { if ($add_history) { // add the change to the history of the issue $summary = User::getFullName($usr_id) . ' added to the authorized repliers list by ' . User::getFullName(Auth::getUserID()); History::add($issue_id, Auth::getUserID(), History::getTypeID('replier_added'), $summary); } } return 1; }
// | along with this program; if not, write to: | // | | // | 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'; $usr_id = Auth::getUserID(); $prj_id = Auth::getCurrentProject(); $tpl = new Template_Helper(); $tpl->setTemplate('view_email.tpl.html'); Auth::checkAuthentication(APP_COOKIE, 'index.php?err=5', true); $issue_id = Support::getIssueFromEmail($_GET['id']); if ($issue_id != 0 && !Issue::canAccess($issue_id, $usr_id) || $issue_id == 0 && User::getRoleByUser($usr_id, $prj_id) < User::ROLE_USER) { $tpl->setTemplate('permission_denied.tpl.html'); $tpl->displayTemplate(); exit; } $email = Support::getEmailDetails($_GET['ema_id'], $_GET['id']); $email['seb_body'] = str_replace('&nbsp;', ' ', $email['seb_body']); $tpl->assign(array('email' => $email, 'issue_id' => $issue_id, 'extra_title' => ev_gettext('Issue #%1$s Email #%3$s: %2$s', $issue_id, $email['sup_subject'], Support::getSequenceByID($_GET['id'])), 'email_accounts' => Email_Account::getAssocList(array_keys(Project::getAssocList(Auth::getUserID())), true), 'recipients' => Mail_Queue::getMessageRecipients(array('customer_email', 'other_email'), $_GET['id']))); if (@$_GET['cat'] == 'list_emails') { $sides = Support::getListingSides($_GET['id']); $tpl->assign(array('previous' => $sides['previous'], 'next' => $sides['next'])); } elseif (@$_GET['cat'] == 'move_email' && Auth::getCurrentRole() >= User::getRoleID('Standard User')) { $res = Support::moveEmail(@$_GET['id'], @$_GET['ema_id'], @$_GET['new_ema_id']); $tpl->assign('move_email_result', $res); $tpl->assign('current_user_prefs', Prefs::get(Auth::getUserID())); } else {
/** * Method used to add a customized warning message to the body * of outgoing emails. * * @access public * @param integer $issue_id The issue ID * @param string $to The recipient of the message * @param string $body The body of the message * @return string The body of the message with the warning message, if appropriate */ function addWarningMessage($issue_id, $to, $body) { $setup = Setup::load(); if (@$setup['email_routing']['status'] == 'enabled' && $setup['email_routing']['warning']['status'] == 'enabled') { // check if the recipient can send emails to the customer $recipient_email = Mail_API::getEmailAddress($to); $recipient_usr_id = User::getUserIDByEmail($recipient_email); // don't add the warning message if the recipient is an unknown email address if (empty($recipient_usr_id)) { return $body; } else { // don't add anything if the recipient is a known customer contact $recipient_role_id = User::getRoleByUser($recipient_usr_id, Issue::getProjectID($issue_id)); if ($recipient_role_id == User::getRoleID('Customer')) { return $body; } else { if (!Support::isAllowedToEmail($issue_id, $recipient_email)) { return Mail_API::getWarningMessage('blocked') . "\n\n" . $body; } else { return Mail_API::getWarningMessage('allowed') . "\n\n" . $body; } } } } else { return $body; } }
/** * Adds an email to the outgoing mail queue. * * @access public * @param string $recipient The recipient of this email * @param array $headers The list of headers that should be sent with this email * @param string $body The body of the message * @param integer $save_email_copy Whether to send a copy of this email to a configurable address or not (eventum_sent@) * @param integer $issue_id The ID of the issue. If false, email will not be associated with issue. * @param string $type The type of message this is. * @param integer $sender_usr_id The id of the user sending this email. * @param integer $type_id The ID of the event that triggered this notification (issue_id, sup_id, not_id, etc) * @return true, or a PEAR_Error object */ function add($recipient, $headers, $body, $save_email_copy = 0, $issue_id = false, $type = '', $sender_usr_id = false, $type_id = false) { // avoid sending emails out to users with inactive status $recipient_email = Mail_API::getEmailAddress($recipient); $usr_id = User::getUserIDByEmail($recipient_email); if (!empty($usr_id)) { $user_status = User::getStatusByEmail($recipient_email); // if user is not set to an active status, then silently ignore if (!User::isActiveStatus($user_status) && !User::isPendingStatus($user_status)) { return false; } } $to_usr_id = User::getUserIDByEmail($recipient_email); $recipient = Mail_API::fixAddressQuoting($recipient); $reminder_addresses = Reminder::_getReminderAlertAddresses(); // add specialized headers if (!empty($issue_id) && (!empty($to_usr_id) && User::getRoleByUser($to_usr_id, Issue::getProjectID($issue_id)) > User::getRoleID("Customer")) || @in_array(Mail_API::getEmailAddress($to), $reminder_addresses)) { $headers += Mail_API::getSpecializedHeaders($issue_id, $type, $headers, $sender_usr_id); } if (empty($issue_id)) { $issue_id = 'null'; } // if the Date: header is missing, add it. if (!in_array('Date', array_keys($headers))) { $headers['Date'] = MIME_Helper::encode(date('D, j M Y H:i:s O')); } if (!empty($headers['To'])) { $headers['To'] = Mail_API::fixAddressQuoting($headers['To']); } list(, $text_headers) = Mail_API::prepareHeaders($headers); $stmt = "INSERT INTO\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "mail_queue\n (\n maq_save_copy,\n maq_queued_date,\n maq_sender_ip_address,\n maq_recipient,\n maq_headers,\n maq_body,\n maq_iss_id,\n maq_subject,\n maq_type"; if ($sender_usr_id != false) { $stmt .= ",\nmaq_usr_id"; } if ($type_id != false) { $stmt .= ",\nmaq_type_id"; } $stmt .= ") VALUES (\n {$save_email_copy},\n '" . Date_API::getCurrentDateGMT() . "',\n '" . getenv("REMOTE_ADDR") . "',\n '" . Misc::escapeString($recipient) . "',\n '" . Misc::escapeString($text_headers) . "',\n '" . Misc::escapeString($body) . "',\n " . Misc::escapeInteger($issue_id) . ",\n '" . Misc::escapeString($headers["Subject"]) . "',\n '{$type}'"; if ($sender_usr_id != false) { $stmt .= ",\n" . $sender_usr_id; } if ($type_id != false) { $stmt .= ",\n" . $type_id; } $stmt .= ")"; $res = $GLOBALS["db_api"]->dbh->query($stmt); if (PEAR::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); return $res; } else { return true; } }
function lookupCustomer($p) { $email = XML_RPC_decode($p->getParam(0)); $password = XML_RPC_decode($p->getParam(1)); $auth = authenticate($email, $password); if (is_object($auth)) { return $auth; } $prj_id = XML_RPC_decode($p->getParam(2)); $field = XML_RPC_decode($p->getParam(3)); $value = XML_RPC_decode($p->getParam(4)); $possible_fields = array('email', 'support', 'customer'); if (!in_array($field, $possible_fields)) { return new XML_RPC_Response(0, $XML_RPC_erruser + 1, "Unknown field type '{$field}'"); } $usr_id = User::getUserIDByEmail($email); // only customers should be able to use this page $role_id = User::getRoleByUser($usr_id, $prj_id); if ($role_id < User::getRoleID('Developer')) { return new XML_RPC_Response(0, $XML_RPC_erruser + 1, "You don't have the appropriate permissions to lookup customer information"); } else { $res = Customer::lookup($prj_id, $field, $value); return new XML_RPC_Response(XML_RPC_Encode($res)); } }
/** * Gets the current role in the current project. * * @access public * @return integer The current role ID */ function getCurrentRole() { $usr_id = Auth::getUserID(); if (!$usr_id) { return 1; } $prj_id = Auth::getCurrentProject(); if (!empty($prj_id) && !empty($usr_id)) { return User::getRoleByUser($usr_id, $prj_id); } else { return 1; } }
/** * 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; }
// +----------------------------------------------------------------------+ // | Authors: Raul Raat <*****@*****.**> | // | Authors: Elan Ruusamäe <*****@*****.**> | // +----------------------------------------------------------------------+ require_once dirname(__FILE__) . '/../../init.php'; // check login Auth::checkAuthentication(APP_COOKIE); $field_name = !empty($_POST['field_name']) ? $_POST['field_name'] : null; $issue_id = !empty($_POST['issue_id']) ? (int) $_POST['issue_id'] : null; // check if correct issue id was sent if (!$issue_id || !Issue::exists($issue_id)) { die('Invalid issue_id'); } $usr_id = Auth::getUserID(); // check if user role is above "Standard User" if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) < User::getRoleID('Standard User')) { die('Forbidden'); } // check if user can acess the issue if (!Issue::canAccess($issue_id, $usr_id)) { die('Forbidden'); } switch ($field_name) { case 'expected_resolution_date': $day = Misc::escapeInteger($_POST['day']); $month = Misc::escapeInteger($_POST['month']); $year = Misc::escapeInteger($_POST['year']); if ($day == 0 && $month == 1 && $year == 0) { // clear button $date = null; } else {
include_once APP_INC_PATH . "class.note.php"; include_once APP_INC_PATH . "class.user.php"; include_once APP_INC_PATH . "db_access.php"; $tpl = new Template_API(); $tpl->setTemplate("view_note.tpl.html"); Auth::checkAuthentication(APP_COOKIE, 'index.php?err=5', true); $usr_id = Auth::getUserID(); $note = Note::getDetails($HTTP_GET_VARS["id"]); if ($note == '') { $tpl->assign("note", ''); $tpl->displayTemplate(); exit; } else { $note["message"] = $note["not_note"]; $issue_id = Note::getIssueID($HTTP_GET_VARS["id"]); $usr_id = Auth::getUserID(); } if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) < User::getRoleID('Standard User') || !Issue::canAccess($issue_id, Auth::getUserID())) { $tpl->setTemplate("permission_denied.tpl.html"); $tpl->displayTemplate(); exit; } $note = Note::getDetails($HTTP_GET_VARS["id"]); $note["message"] = $note["not_note"]; $issue_id = Note::getIssueID($HTTP_GET_VARS["id"]); $tpl->bulkAssign(array("note" => $note, "issue_id" => $issue_id, 'extra_title' => "Note #" . $HTTP_GET_VARS['num'] . ": " . $note['not_title'])); if (!empty($issue_id)) { $sides = Note::getSideLinks($issue_id, $HTTP_GET_VARS["id"]); $tpl->assign(array('previous' => $sides['previous'], 'next' => $sides['next'])); } $tpl->displayTemplate();
/** * Gets the current role in the current project. * * @return integer The current role ID */ public static function getCurrentRole() { $prj_id = self::getCurrentProject(); $usr_id = self::getUserID(); if (!empty($prj_id) && !empty($usr_id)) { return User::getRoleByUser($usr_id, $prj_id); } else { return 1; } }
/** * 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; }
$email = Mail_API::getEmailAddress($senders[$i]); $sender_emails[$email] = $senders[$i]; } $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); } } } }
/** * 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('view_note.tpl.html'); Auth::checkAuthentication(APP_COOKIE, 'index.php?err=5', true); $usr_id = Auth::getUserID(); $note_id = $_GET['id']; $note = Note::getDetails($note_id); if ($note == '') { $tpl->assign('note', ''); $tpl->displayTemplate(); exit; } else { $note['message'] = $note['not_note']; $issue_id = Note::getIssueID($note_id); $usr_id = Auth::getUserID(); } if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) < User::getRoleID('Standard User') || !Access::canViewInternalNotes($issue_id, Auth::getUserID())) { $tpl->setTemplate('permission_denied.tpl.html'); $tpl->displayTemplate(); exit; } $note = Note::getDetails($_GET['id']); $note['message'] = $note['not_note']; $issue_id = Note::getIssueID($_GET['id']); $tpl->assign(array('note' => $note, 'issue_id' => $issue_id, 'extra_title' => 'Note #' . Note::getNoteSequenceNumber($issue_id, $note_id) . ': ' . $note['not_title'], 'recipients' => Mail_Queue::getMessageRecipients('notes', $note_id))); if (!empty($issue_id)) { $sides = Note::getSideLinks($issue_id, $_GET['id']); $tpl->assign(array('previous' => $sides['previous'], 'next' => $sides['next'])); } $tpl->displayTemplate();
/** * Processes the template and assigns common variables automatically. * * @access private */ function processTemplate() { global $HTTP_SERVER_VARS; // determine the correct CSS file to use if (ereg('MSIE ([0-9].[0-9]{1,2})', @$HTTP_SERVER_VARS["HTTP_USER_AGENT"], $log_version)) { $user_agent = 'ie'; } else { $user_agent = 'other'; } $this->assign("user_agent", $user_agent); // create the list of projects $usr_id = Auth::getUserID(); if ($usr_id != '') { $prj_id = Auth::getCurrentProject(); if (!empty($prj_id)) { $role_id = User::getRoleByUser($usr_id, $prj_id); $this->assign("current_project", $prj_id); $this->assign("current_project_name", Auth::getCurrentProjectName()); $has_customer_integration = Customer::hasCustomerIntegration($prj_id); $this->assign("has_customer_integration", $has_customer_integration); if ($has_customer_integration) { $this->assign("customer_backend_name", Customer::getBackendImplementationName($prj_id)); } if ($role_id == User::getRoleID('administrator') || $role_id == User::getRoleID('manager')) { $this->assign("show_admin_link", true); } if ($role_id > 0) { $this->assign("current_role", (int) $role_id); $this->assign("current_role_name", User::getRole($role_id)); } } $info = User::getNameEmail($usr_id); $this->assign("active_projects", Project::getAssocList($usr_id)); $this->assign("current_full_name", $info["usr_full_name"]); $this->assign("current_email", $info["usr_email"]); $this->assign("current_user_id", $usr_id); $this->assign("is_current_user_clocked_in", User::isClockedIn($usr_id)); $this->assign("roles", User::getAssocRoleIDs()); } $this->assign("app_setup", Setup::load()); $this->assign("app_setup_path", APP_SETUP_PATH); $this->assign("app_setup_file", APP_SETUP_FILE); $this->assign("application_version", APP_VERSION); $this->assign("application_title", APP_NAME); $this->assign("app_base_url", APP_BASE_URL); $this->assign("rel_url", APP_RELATIVE_URL); $this->assign("lang", APP_CURRENT_LANG); $this->assign("SID", SID); // now for the browser detection stuff Net_UserAgent_Detect::detect(); $this->assign("browser", Net_UserAgent_Detect::_getStaticProperty('browser')); $this->assign("os", Net_UserAgent_Detect::_getStaticProperty('os')); // this is only used by the textarea resize script $js_script_name = str_replace('/', '_', str_replace('.php', '', $HTTP_SERVER_VARS['PHP_SELF'])); $this->assign("js_script_name", $js_script_name); $this->assign("total_queries", $GLOBALS['TOTAL_QUERIES']); $this->assign(array("cell_color" => APP_CELL_COLOR, "light_color" => APP_LIGHT_COLOR, "middle_color" => APP_MIDDLE_COLOR, "dark_color" => APP_DARK_COLOR, "cycle" => APP_CYCLE_COLORS, "internal_color" => APP_INTERNAL_COLOR)); }
/** * Method used to get the list of custom fields and custom field * values associated with a given issue ID. If usr_id is false method * defaults to current user. * * @param integer $prj_id The project ID * @param integer $iss_id The issue ID * @param integer $usr_id The ID of the user who is going to be viewing this list. * @param mixed $form_type The name of the form this is for or if this is an array the ids of the fields to return * @return array The list of custom fields */ public static function getListByIssue($prj_id, $iss_id, $usr_id = null, $form_type = false) { if (!$usr_id) { $usr_id = Auth::getUserID(); } $usr_role = User::getRoleByUser($usr_id, $prj_id); if (empty($usr_role)) { $usr_role = 0; } $stmt = 'SELECT fld_id, fld_title, fld_type, fld_report_form_required, fld_anonymous_form_required, fld_close_form_required, ' . self::getDBValueFieldSQL() . ' as value, icf_value, icf_value_date, icf_value_integer, fld_min_role, fld_description FROM ( {{%custom_field}}, {{%project_custom_field}} ) LEFT JOIN {{%issue_custom_field}} ON pcf_fld_id=icf_fld_id AND icf_iss_id=? WHERE pcf_fld_id=fld_id AND pcf_prj_id=? AND fld_min_role <= ?'; $params = array($iss_id, $prj_id, $usr_role); if ($form_type != false) { if (is_array($form_type)) { $stmt .= ' AND fld_id IN(' . DB_Helper::buildList($form_type) . ')'; $params = array_merge($params, $form_type); } else { $fld_name = 'fld_' . Misc::escapeString($form_type); $stmt .= " AND {$fld_name}=1"; } } $stmt .= ' ORDER BY fld_rank ASC'; try { $res = DB_Helper::getInstance()->getAll($stmt, $params); } catch (DbException $e) { return array(); } if (count($res) == 0) { return array(); } $fields = array(); foreach ($res as &$row) { if ($row['fld_type'] == 'combo') { $row['selected_cfo_id'] = $row['value']; $row['original_value'] = $row['value']; $row['value'] = self::getOptionValue($row['fld_id'], $row['value']); $row['field_options'] = self::getOptions($row['fld_id'], false, $iss_id); // add the select option to the list of values if it isn't on the list (useful for fields with active and non-active items) if (!empty($row['original_value']) && !isset($row['field_options'][$row['original_value']])) { $row['field_options'][$row['original_value']] = self::getOptionValue($row['fld_id'], $row['original_value']); } $fields[] = $row; } elseif ($row['fld_type'] == 'multiple' || $row['fld_type'] == 'checkbox') { // check whether this field is already in the array $found = 0; foreach ($fields as $y => $field) { if ($field['fld_id'] == $row['fld_id']) { $found = 1; $found_index = $y; } } $original_value = $row['value']; if (!$found) { $row['selected_cfo_id'] = array($row['value']); $row['value'] = self::getOptionValue($row['fld_id'], $row['value']); $row['field_options'] = self::getOptions($row['fld_id']); $fields[] = $row; $found_index = count($fields) - 1; } else { $fields[$found_index]['value'] .= ', ' . self::getOptionValue($row['fld_id'], $row['value']); $fields[$found_index]['selected_cfo_id'][] = $row['value']; } // add the select option to the list of values if it isn't on the list (useful for fields with active and non-active items) if ($original_value !== null && !in_array($original_value, $fields[$found_index]['field_options'])) { $fields[$found_index]['field_options'][$original_value] = self::getOptionValue($row['fld_id'], $original_value); } } else { $row['value'] = $row[self::getDBValueFieldNameByType($row['fld_type'])]; $fields[] = $row; } } foreach ($fields as $key => $field) { $backend = self::getBackend($field['fld_id']); if (is_object($backend) && is_subclass_of($backend, 'Dynamic_Custom_Field_Backend')) { $fields[$key]['dynamic_options'] = $backend->getStructuredData(); $fields[$key]['controlling_field_id'] = $backend->getControllingCustomFieldID(); $fields[$key]['controlling_field_name'] = $backend->getControllingCustomFieldName(); $fields[$key]['hide_when_no_options'] = $backend->hideWhenNoOptions(); $fields[$key]['lookup_method'] = $backend->lookupMethod(); } // check if the backend implements "isRequired" if (is_object($backend) && method_exists($backend, 'isRequired')) { $fields[$key]['fld_report_form_required'] = $backend->isRequired($fields[$key]['fld_id'], 'report', $iss_id); $fields[$key]['fld_anonymous_form_required'] = $backend->isRequired($fields[$key]['fld_id'], 'anonymous', $iss_id); $fields[$key]['fld_close_form_required'] = $backend->isRequired($fields[$key]['fld_id'], 'close', $iss_id); } if (is_object($backend) && method_exists($backend, 'getValidationJS')) { $fields[$key]['validation_js'] = $backend->getValidationJS($fields[$key]['fld_id'], $form_type, $iss_id); } else { $fields[$key]['validation_js'] = ''; } } return $fields; }
/** * Method used to update the details of the project information. * * @return integer 1 if the update worked, -1 otherwise */ public static function update() { if (Validation::isWhitespace($_POST['title'])) { return -2; } $stmt = 'UPDATE {{%project}} SET prj_title=?, prj_status=?, prj_lead_usr_id=?, prj_initial_sta_id=?, prj_outgoing_sender_name=?, prj_outgoing_sender_email=?, prj_mail_aliases=?, prj_remote_invocation=?, prj_segregate_reporter=?, prj_customer_backend=?, prj_workflow_backend=? WHERE prj_id=?'; try { DB_Helper::getInstance()->query($stmt, array($_POST['title'], $_POST['status'], $_POST['lead_usr_id'], $_POST['initial_status'], $_POST['outgoing_sender_name'], $_POST['outgoing_sender_email'], $_POST['mail_aliases'], $_POST['remote_invocation'], $_POST['segregate_reporter'], $_POST['customer_backend'], $_POST['workflow_backend'], $_POST['id'])); } catch (DbException $e) { return -1; } self::removeUserByProjects(array($_POST['id']), $_POST['users']); foreach ($_POST['users'] as $user) { if ($user == $_POST['lead_usr_id']) { self::associateUser($_POST['id'], $user, User::getRoleID('Manager')); } elseif (User::getRoleByUser($user, $_POST['id']) == '') { // users who are now being associated with this project should be set to 'Standard User' self::associateUser($_POST['id'], $user, User::getRoleID('Standard User')); } } $statuses = array_keys(Status::getAssocStatusList($_POST['id'])); if (count($statuses) > 0) { Status::removeProjectAssociations($statuses, $_POST['id']); } foreach ($_POST['statuses'] as $sta_id) { Status::addProjectAssociation($sta_id, $_POST['id']); } return 1; }
/** * Adds a real user to the authorized repliers list. * * @param integer $issue_id The id of the issue. * @param integer $usr_id The id of the user. * @param boolean $add_history If this should be logged. */ public static function addUser($issue_id, $usr_id, $add_history = true) { // don't add customers to this list. They should already be able to send if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) == User::getRoleID('Customer')) { return -2; } $stmt = 'INSERT INTO {{%issue_user_replier}} ( iur_iss_id, iur_usr_id ) VALUES ( ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array($issue_id, $usr_id)); } catch (DbException $e) { return -1; } if ($add_history) { // add the change to the history of the issue $current_usr_id = Auth::getUserID(); History::add($issue_id, $current_usr_id, 'replier_added', '{other_user} added to the authorized repliers list by {user}', array('other_user' => User::getFullName($usr_id), 'user' => User::getFullName($current_usr_id))); } return 1; }
/** * Method to determine if user can access a particular issue * * @access public * @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 */ function canAccess($issue_id, $usr_id) { static $access; if (empty($issue_id)) { return true; } 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 = Issue::getProjectID($issue_id); // check customer permissions if (Customer::hasCustomerIntegration($details['iss_prj_id']) && $usr_role == User::getRoleID("Customer") && $details['iss_customer_id'] != $usr_details['usr_customer_id']) { $return = false; } elseif ($details['iss_private'] == 1) { // check if the issue is even private // check role, reporter, assigment and group if (User::getRoleByUser($usr_id, $details['iss_prj_id']) > 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("Standard User") && Project::getSegregateReporters($prj_id) && $details['iss_usr_id'] != $usr_id && !Issue::isAssignedToUser($issue_id, $usr_id) && !Authorized_Replier::isUserAuthorizedReplier($issue_id, $usr_id)) { return false; } else { $return = true; } $access[$issue_id . "-" . $usr_id] = $return; return $return; }