diff --git a/include/class.config.php b/include/class.config.php index 73261e24c3df3547f3bbce2e3d2dadc48662e3b9..a33f231d6bff4b7277065b8d4ca2794fe5d2f827 100644 --- a/include/class.config.php +++ b/include/class.config.php @@ -680,19 +680,20 @@ class OsticketConfig extends Config { return ($this->get('message_alert_acct_manager')); } - function alertONNewNote() { + //TODO: change note_alert to activity_alert + function alertONNewActivity() { return ($this->get('note_alert_active')); } - function alertLastRespondentONNewNote() { + function alertLastRespondentONNewActivity() { return ($this->get('note_alert_laststaff')); } - function alertAssignedONNewNote() { + function alertAssignedONNewActivity() { return ($this->get('note_alert_assigned')); } - function alertDeptManagerONNewNote() { + function alertDeptManagerONNewActivity() { return ($this->get('note_alert_dept_manager')); } diff --git a/include/class.thread.php b/include/class.thread.php index 019cd8b65df15eafea32e5db56799698f83fc482..45586bf89f9d2aa5672b0bdbd2fdbb8890cdbfb1 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -237,7 +237,7 @@ class Thread { } -Class ThreadEntry { +class ThreadEntry { var $id; var $ht; @@ -339,6 +339,10 @@ Class ThreadEntry { return db_query($sql) && db_affected_rows(); } + function getMessage() { + return $this->getBody(); + } + function getCreateDate() { return $this->ht['created']; } @@ -1305,10 +1309,6 @@ class Note extends ThreadEntry { parent::ThreadEntry($id, 'N', $ticketId); } - function getMessage() { - return $this->getBody(); - } - /* static */ function create($vars, &$errors) { return self::lookup(self::add($vars, $errors)); diff --git a/include/class.ticket.php b/include/class.ticket.php index e4f5a8b7721b2c451627817ff2ec40b1f6d989cb..148f4f7d91e1e1896ec65279da7a20790211f2a0 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -1081,9 +1081,15 @@ class Ticket { return true; } - function onResponse() { + function onResponse($response, $options=array()) { db_query('UPDATE '.TICKET_TABLE.' SET isanswered=1, lastresponse=NOW(), updated=NOW() WHERE ticket_id='.db_input($this->getId())); $this->reload(); + $vars = array_merge($options, + array( + 'activity' => _S('New Response'), + 'threadentry' => $response)); + + $this->onActivity($vars); } /* @@ -1212,6 +1218,86 @@ class Ticket { } } + function onActivity($vars, $alert=true) { + global $cfg, $thisstaff; + + //TODO: do some shit + + if (!$alert // Check if alert is enabled + || !$cfg->alertONNewActivity() + || !($dept=$this->getDept()) + || !($email=$cfg->getAlertEmail()) + || !($tpl = $dept->getTemplate()) + || !($msg=$tpl->getNoteAlertMsgTemplate())) + return; + + // Alert recipients + $recipients=array(); + + //Last respondent. + if ($cfg->alertLastRespondentONNewActivity()) + $recipients[] = $this->getLastRespondent(); + + // Assigned staff / team + if ($cfg->alertAssignedONNewActivity()) { + + if (isset($vars['assignee']) + && $vars['assignee'] instanceof Staff) + $recipients[] = $vars['assignee']; + elseif ($this->isOpen() && ($assignee = $this->getStaff())) + $recipients[] = $assignee; + + if ($team = $this->getTeam()) + $recipients = array_merge($recipients, $team->getMembers()); + } + + // Dept manager + if ($cfg->alertDeptManagerONNewActivity() && $dept && $dept->getManagerId()) + $recipients[] = $dept->getManager(); + + $options = array(); + $staffId = $thisstaff ? $thisstaff->getId() : 0; + if ($vars['threadentry'] && $vars['threadentry'] instanceof ThreadEntry) { + $options = array( + 'inreplyto' => $vars['threadentry']->getEmailMessageId(), + 'references' => $vars['threadentry']->getEmailReferences(), + 'thread' => $vars['threadentry']); + + // Activity details + if (!$vars['comments']) + $vars['comments'] = $vars['threadentry']; + + // Staff doing the activity + $staffId = $vars['threadentry']->getStaffId() ?: $staffId; + } + + $msg = $this->replaceVars($msg->asArray(), + array( + 'note' => $vars['threadentry'], // For compatibility + 'activity' => $vars['activity'], + 'comments' => $vars['comments'])); + + $isClosed = $this->isClosed(); + $sentlist=array(); + foreach ($recipients as $k=>$staff) { + if (!is_object($staff) + // Don't bother vacationing staff. + || !$staff->isAvailable() + // No need to alert the poster! + || $staffId == $staff->getId() + // No duplicates. + || isset($sentlist[$staff->getEmail()]) + // Make sure staff has access to ticket + || ($isClosed && !$this->checkStaffAccess($staff)) + ) + continue; + $alert = $this->replaceVars($msg, array('recipient' => $staff)); + $email->sendAlert($staff, $alert['subj'], $alert['body'], null, $options); + $sentlist[$staff->getEmail()] = 1; + } + + } + function onAssign($assignee, $comments, $alert=true) { global $cfg, $thisstaff; @@ -1841,6 +1927,7 @@ class Ticket { if(!($response = $this->getThread()->addResponse($vars, $errors))) return null; + $assignee = $this->getStaff(); // Set status - if checked. if ($vars['reply_status_id'] && $vars['reply_status_id'] != $this->getStatusId()) @@ -1850,10 +1937,11 @@ class Ticket { && $cfg->autoClaimTickets()) $this->setStaffId($thisstaff->getId()); //direct assignment; - $this->onResponse(); //do house cleaning.. + + $this->onResponse($response, array('assignee' => $assignee)); //do house cleaning.. /* email the user?? - if disabled - then bail out */ - if(!$alert) return $response; + if (!$alert) return $response; $dept = $this->getDept(); @@ -1979,62 +2067,12 @@ class Ticket { $this->reload(); } - // If alerts are not enabled then return a success. - if(!$alert || !$cfg->alertONNewNote() || !($dept=$this->getDept())) - return $note; - - if (($email = $dept->getAlertEmail()) - && ($tpl = $dept->getTemplate()) - && ($msg=$tpl->getNoteAlertMsgTemplate())) { - - $msg = $this->replaceVars($msg->asArray(), - array('note' => $note)); - - // Alert recipients - $recipients=array(); - - //Last respondent. - if ($cfg->alertLastRespondentONNewNote()) - $recipients[] = $this->getLastRespondent(); - - // Assigned staff / team - if ($cfg->alertAssignedONNewNote()) { - - if ($assignee && $assignee instanceof Staff) - $recipients[] = $assignee; - - if ($team = $this->getTeam()) - $recipients = array_merge($recipients, $team->getMembers()); - } - - // Dept manager - if ($cfg->alertDeptManagerONNewNote() && $dept && $dept->getManagerId()) - $recipients[] = $dept->getManager(); - - $options = array( - 'inreplyto'=>$note->getEmailMessageId(), - 'references'=>$note->getEmailReferences(), - 'thread'=>$note); - - $isClosed = $this->isClosed(); - $sentlist=array(); - foreach( $recipients as $k=>$staff) { - if(!is_object($staff) - // Don't bother vacationing staff. - || !$staff->isAvailable() - // No duplicates. - || isset($sentlist[$staff->getEmail()]) - // No need to alert the poster! - || $note->getStaffId() == $staff->getId() - // Make sure staff has access to ticket - || ($isClosed && !$this->checkStaffAccess($staff)) - ) - continue; - $alert = $this->replaceVars($msg, array('recipient' => $staff)); - $email->sendAlert($staff, $alert['subj'], $alert['body'], null, $options); - $sentlist[$staff->getEmail()] = 1; - } - } + $activity = $vars['activity'] ?: _S('New Internal Note'); + $this->onActivity(array( + 'activity' => $activity, + 'threadentry' => $note, + 'assignee' => $assignee + ), $alert); return $note; } diff --git a/include/i18n/en_US/help/tips/settings.alerts.yaml b/include/i18n/en_US/help/tips/settings.alerts.yaml index 323e1bba55882b32dc31c9cdcc725b2e6aa55052..21951c9e9595c1f911f4c95b50602ea03595ace6 100644 --- a/include/i18n/en_US/help/tips/settings.alerts.yaml +++ b/include/i18n/en_US/help/tips/settings.alerts.yaml @@ -42,10 +42,10 @@ message_alert: href: /scp/templates.php?default_for=message.alert internal_note_alert: - title: New Internal Note Alert + title: New Internal Activity Alert content: > - Alert sent out to Agents when a new <span - class="doc-desc-title">Internal Note</span> is appended to a ticket. + Alert sent out to Agents when internal activity such as an internal + note or an agent reply is appended to a ticket. links: - title: Default Ticket Activity Template href: /scp/templates.php?default_for=note.alert diff --git a/include/i18n/en_US/templates/email/note.alert.yaml b/include/i18n/en_US/templates/email/note.alert.yaml index a704830d6bb3300607be5b3c7f0c6a55741b4955..5a1bcd91e3d69d21fe5b61ba4e1ab7cc9d2405e1 100644 --- a/include/i18n/en_US/templates/email/note.alert.yaml +++ b/include/i18n/en_US/templates/email/note.alert.yaml @@ -6,14 +6,14 @@ # --- notes: | - Sent to staff members when a new internal note is appended to a ticket. - Internal notes can only be added by staff members. + Alert sent out to Agents when internal activity such as an internal + note or an agent reply is appended to a ticket. subject: | - New Internal Note Alert + New Internal Activity Alert body: | <h3><strong>Hi %{recipient.name},</strong></h3> - An internal note has been appended to ticket <a + An agent has logged activity on ticket <a href="%{ticket.staff_link}">#%{ticket.number}</a> <br> <br> diff --git a/include/pear/Mail.php b/include/pear/Mail.php index 75132ac2a6c3e9d99bd1784feb41154f0cd71d3d..5d4d3b09dd61c14a501cc52cb8d2f9f1499bb98a 100644 --- a/include/pear/Mail.php +++ b/include/pear/Mail.php @@ -74,14 +74,16 @@ class Mail function &factory($driver, $params = array()) { $driver = strtolower($driver); - @include_once 'Mail/' . $driver . '.php'; $class = 'Mail_' . $driver; + if (!class_exists($class)) + include_once PEAR_DIR.'Mail/' . $driver . '.php'; + if (class_exists($class)) { $mailer = new $class($params); return $mailer; - } else { - return PEAR::raiseError('Unable to find class for driver ' . $driver); } + + return PEAR::raiseError('Unable to find class for driver ' . $driver); } /** diff --git a/include/staff/settings-alerts.inc.php b/include/staff/settings-alerts.inc.php index 14b3fee30ade06c2b8d190b83e276cb295dd2351..3a9326bc4127343b57831a14a81b8d50f1b5c5bb 100644 --- a/include/staff/settings-alerts.inc.php +++ b/include/staff/settings-alerts.inc.php @@ -88,7 +88,7 @@ <?php echo __('Organization Account Manager'); ?> </td> </tr> - <tr><th><em><b><?php echo __('New Internal Note Alert'); ?></b>: + <tr><th><em><b><?php echo __('New Internal Activity Alert'); ?></b>: <i class="help-tip icon-question-sign" href="#internal_note_alert"></i> </em></th></tr> <tr>