/** * Method used to log the changes made against a specific issue. * * @param integer $iss_id The issue ID * @param integer $usr_id The ID of the user. * @param integer|string $htt_id The type ID of this history event. * @param string $summary The summary of the changes * @param array $context parameters used in summary */ public static function add($iss_id, $usr_id, $htt_id, $summary, $context = array()) { if (!is_numeric($htt_id)) { $htt_id = History::getTypeID($htt_id); } $params = array('his_iss_id' => $iss_id, 'his_usr_id' => $usr_id, 'his_created_date' => Date_Helper::getCurrentDateGMT(), 'his_summary' => $summary, 'his_context' => json_encode($context), 'his_htt_id' => $htt_id); $stmt = 'INSERT INTO {{%issue_history}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { } }
/** * Insert note to system, send out notification and log. * * @param int $usr_id The user ID * @param int $issue_id The issue ID * @param string $title Title of the note * @param string $note Note contents * @param array $options extra optional options: * - (array) cc: extra recipients to notify (usr_id list) * - (bool) add_extra_recipients: whether to add recipients in 'cc' to notification list * - (bool) closing: If The issue is being closed. Default false * - (bool) is_blocked: FIXME * - (bool) log: If adding this note should be logged. Default true * - (bool) send_notification: Whether to send a notification about this note or not. Default true * - (int) parent_id: FIXME * - (string) full_message: FIXME * - (string) message_id: FIXME * - (string) unknown_user: The email address of a user that sent the blocked email that was turned into this note * @return int the new note id if the insert worked, -1 or -2 otherwise */ public static function insertNote($usr_id, $issue_id, $title, $note, $options = array()) { if (Validation::isWhitespace($note)) { return -2; } $options = array_merge(array('unknown_user' => null, 'log' => true, 'closing' => false, 'send_notification' => true, 'is_blocked' => false, 'message_id' => null, 'cc' => null, 'full_message' => null, 'parent_id' => null), $options); $prj_id = Issue::getProjectID($issue_id); // NOTE: workflow may modify the parameters as $data is passed as reference $data = array('title' => &$title, 'note' => &$note, 'options' => $options); $workflow = Workflow::preNoteInsert($prj_id, $issue_id, $data); if ($workflow !== null) { // cancel insert of note return $workflow; } // add the poster to the list of people to be subscribed to the notification list // only if there is no 'unknown user' and the note is not blocked if (!$options['unknown_user'] && !$options['is_blocked']) { $note_cc = $options['add_extra_recipients'] ? $options['cc'] : array(); // always add the current user to the note_cc list $note_cc[] = $usr_id; $actions = Notification::getDefaultActions($issue_id, User::getEmail($usr_id), 'note'); foreach ($note_cc as $subscriber_usr_id) { Notification::subscribeUser($usr_id, $issue_id, $subscriber_usr_id, $actions); } } $params = array('not_iss_id' => $issue_id, 'not_usr_id' => $usr_id, 'not_created_date' => Date_Helper::getCurrentDateGMT(), 'not_note' => $note, 'not_title' => $title, 'not_message_id' => $options['message_id'] ?: Mail_Helper::generateMessageID()); if ($options['full_message']) { $params['not_full_message'] = $options['full_message']; } if ($options['is_blocked']) { $params['not_is_blocked'] = '1'; } if ($options['parent_id']) { $params['not_parent_id'] = $options['parent_id']; } if ($options['unknown_user']) { $params['not_unknown_user'] = $options['unknown_user']; } $stmt = 'INSERT INTO {{%note}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } $note_id = DB_Helper::get_last_insert_id(); Issue::markAsUpdated($issue_id, 'note'); if ($options['log']) { // need to save a history entry for this History::add($issue_id, $usr_id, 'note_added', 'Note added by {subject}', array('subject' => User::getFullName($usr_id))); } // send notifications for the issue being updated if ($options['send_notification']) { $internal_only = true; Notification::notify($issue_id, 'notes', $note_id, $internal_only, $options['cc']); Workflow::handleNewNote($prj_id, $issue_id, $usr_id, $options['closing'], $note_id); } // need to return the new note id here so it can // be re-used to associate internal-only attachments return $note_id; }
/** * Sets the quarantine status. Optionally an expiration date can be set * to indicate when the quarantine expires. A status > 0 indicates that quarantine is active. * * @param integer $issue_id The issue ID * @param integer $status The quarantine status * @param string $expiration The expiration date of quarantine (default empty) * @return int */ public static function setQuarantine($issue_id, $status, $expiration = '') { $issue_id = (int) $issue_id; $status = (int) $status; // see if there is an existing record $stmt = 'SELECT COUNT(*) FROM {{%issue_quarantine}} WHERE iqu_iss_id = ?'; try { $res = DB_Helper::getInstance()->getOne($stmt, array($issue_id)); } catch (DbException $e) { return -1; } if ($res > 0) { // update $stmt = 'UPDATE {{%issue_quarantine}} SET iqu_status = ?'; $params = array($status); if (!empty($expiration)) { $stmt .= ",\niqu_expiration = ?"; $params[] = $expiration; } $stmt .= "\nWHERE\n iqu_iss_id = ?"; $params[] = $issue_id; try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } // add history entry about this change taking place if ($status == 0) { $usr_id = Auth::getUserID(); History::add($issue_id, $usr_id, 'issue_quarantine_removed', 'Issue quarantine status cleared by {user}', array('user' => User::getFullName(Auth::getUserID()))); } return 1; } // insert $params = array('iqu_iss_id' => $issue_id, 'iqu_status' => $status); if (!empty($expiration)) { $params['iqu_expiration'] = $expiration; } $stmt = 'INSERT INTO {{%issue_quarantine}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } return 1; }
/** * Method used to update the account details for a specific user. * * @param $usr_id * @param $data * @param bool $notify * @return integer 1 if the update worked, -1 otherwise */ public static function update($usr_id, $data, $notify = true) { // system account should not be updateable if ($usr_id == APP_SYSTEM_USER_ID) { return 1; } $params = array('usr_email' => $data['email']); if (isset($data['full_name'])) { $params['usr_full_name'] = $data['full_name']; } if (isset($data['grp_id'])) { $params['usr_grp_id'] = !empty($data['grp_id']) ? $data['grp_id'] : null; } if (!empty($data['password'])) { $params['usr_password'] = Auth::hashPassword($data['password']); } if (isset($data['external_id'])) { $params['usr_external_id'] = $data['external_id']; } if (isset($data['par_code'])) { $params['usr_par_code'] = $data['par_code']; } $stmt = 'UPDATE {{%user}} SET ' . DB_Helper::buildSet($params) . ' WHERE usr_id=?'; $params[] = $usr_id; try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } if (isset($data['role'])) { // update the project associations now $stmt = 'DELETE FROM {{%project_user}} WHERE pru_usr_id=?'; try { DB_Helper::getInstance()->query($stmt, array($usr_id)); } catch (DbException $e) { return -1; } foreach ($data['role'] as $prj_id => $role) { if ($role < 1) { continue; } $stmt = 'INSERT INTO {{%project_user}} ( pru_prj_id, pru_usr_id, pru_role ) VALUES ( ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array($prj_id, $usr_id, $role)); } catch (DbException $e) { return -1; } } } if ($notify == true) { if (!empty($data['password'])) { Notification::notifyUserPassword($usr_id, $data['password']); } else { Notification::notifyUserAccount($usr_id); } } return 1; }
/** * Method used to add a new support email to the system. * * @param array $row The support email details * @param object $structure The email structure object * @param integer $sup_id The support ID to be passed out * @param boolean $closing If this email comes from closing the issue * @return integer 1 if the insert worked, -1 otherwise */ public static function insertEmail($row, &$structure, &$sup_id, $closing = false) { // get usr_id from FROM header $usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($row['from'])); if (!empty($usr_id) && empty($row['customer_id'])) { $row['customer_id'] = User::getCustomerID($usr_id); } if (empty($row['customer_id'])) { $row['customer_id'] = null; } // try to get the parent ID $reference_message_id = Mail_Helper::getReferenceMessageID($row['full_email']); $parent_id = ''; if (!empty($reference_message_id)) { $parent_id = self::getIDByMessageID($reference_message_id); // make sure it is in the same issue if (!empty($parent_id) && (empty($row['issue_id']) || @$row['issue_id'] != self::getIssueFromEmail($parent_id))) { $parent_id = ''; } } $params = array('sup_ema_id' => $row['ema_id'], 'sup_iss_id' => $row['issue_id'], 'sup_customer_id' => $row['customer_id'], 'sup_message_id' => $row['message_id'] ?: '', 'sup_date' => $row['date'], 'sup_from' => $row['from'], 'sup_to' => $row['to'], 'sup_cc' => $row['cc'], 'sup_subject' => $row['subject'] ?: '', 'sup_has_attachment' => $row['has_attachment']); if (!empty($parent_id)) { $params['sup_parent_id'] = $parent_id; } if (!empty($usr_id)) { $params['sup_usr_id'] = $usr_id; } $stmt = 'INSERT INTO {{%support_email}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } $new_sup_id = DB_Helper::get_last_insert_id(); $sup_id = $new_sup_id; $row['sup_id'] = $sup_id; // now add the body and full email to the separate table $stmt = 'INSERT INTO {{%support_email_body}} ( seb_sup_id, seb_body, seb_full_email ) VALUES ( ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array($new_sup_id, $row['body'], $row['full_email'])); } catch (DbException $e) { return -1; } if (!empty($row['issue_id'])) { $prj_id = Issue::getProjectID($row['issue_id']); } elseif (!empty($row['ema_id'])) { $prj_id = Email_Account::getProjectID($row['ema_id']); } else { $prj_id = false; } // FIXME: $row['ema_id'] is empty when mail is sent via convert note! if ($prj_id !== false) { Workflow::handleNewEmail($prj_id, @$row['issue_id'], $structure, $row, $closing); } return 1; }
/** * Method used to add an attachment to the database. * * @param integer $issue_id The issue ID * @param integer $usr_id The user ID * @param string $description The description for this new attachment * @param boolean $internal_only Whether this attachment is supposed to be internal only or not * @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 * @return integer The new attachment ID */ public static function add($issue_id, $usr_id, $description, $internal_only = false, $unknown_user = null, $associated_note_id = null) { if ($internal_only) { $attachment_status = 'internal'; } else { $attachment_status = 'public'; } $params = array('iat_iss_id' => $issue_id, 'iat_usr_id' => $usr_id, 'iat_created_date' => Date_Helper::getCurrentDateGMT(), 'iat_description' => $description, 'iat_status' => $attachment_status); if ($unknown_user) { $params['iat_unknown_user'] = $unknown_user; } if ($associated_note_id) { $params['iat_not_id'] = $associated_note_id; } $stmt = 'INSERT INTO {{%issue_attachment}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return false; } return DB_Helper::get_last_insert_id(); }
* * @copyright (c) Eventum Team * @license GNU General Public License, version 2 or later (GPL-2+) * * For the full copyright and license information, * please see the COPYING and AUTHORS files * that were distributed with this source code. */ /* * Update database fields with fixEncoding instead doing that runtime */ /** @var DbInterface $db */ $logger = Logger::getInstance('db'); $res = $db->getAll("SELECT sup_id,sup_subject,sup_from,sup_to,sup_cc FROM {{%support_email}} WHERE concat(sup_subject,sup_from,sup_to,sup_cc) LIKE '%=?%'"); $changed = 0; foreach ($res as $idx => $row) { $params = array(); foreach ($row as $k => $v) { $params[$k] = Mime_Helper::fixEncoding($v); } if ($row == $params) { $logger->warning("sup_id={$row['sup_id']} no changes", array('sup_id' => $row['sup_id'], 'old' => $row)); continue; } $logger->info("updated sup_id={$row['sup_id']}", array('sup_id' => $row['sup_id'], 'old' => $row, 'new' => $params)); $params[] = $row['sup_id']; $db->query('UPDATE {{%support_email}} SET ' . DB_Helper::buildSet($row) . ' WHERE sup_id=?', $params); $changed++; } $count = count($res); $logger->info("Updated {$changed} out of {$count} entries");
/** * 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 save the IRC notification message in the queue table. * * @param integer $project_id The ID of the project. * @param string $notice The notification summary that should be displayed on IRC * @param bool|integer $issue_id The issue ID * @param bool|integer $usr_id The ID of the user to notify * @param bool|string $category The category of this notification * @param bool|string $type The type of notification (new_issue, etc) * @return bool */ public static function notifyIRC($project_id, $notice, $issue_id = false, $usr_id = false, $category = false, $type = false) { // don't save any irc notification if this feature is disabled $setup = Setup::get(); if ($setup['irc_notification'] != 'enabled') { return false; } $notice = Workflow::formatIRCMessage($project_id, $notice, $issue_id, $usr_id, $category, $type); if ($notice === false) { return; } $params = array('ino_prj_id' => $project_id, 'ino_created_date' => Date_Helper::getCurrentDateGMT(), 'ino_status' => 'pending', 'ino_message' => $notice, 'ino_category' => $category); if ($issue_id) { $params['ino_iss_id'] = $issue_id; } if ($usr_id) { $params['ino_target_usr_id'] = $usr_id; } $stmt = 'INSERT INTO {{%irc_notice}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return false; } return true; }