Newer
Older
$this->setLastMsgId($message->getId());
}
//DeptId can NOT be 0. No orphans please!
Peter Rotich
committed
function setDeptId($deptId) {
// Make sure it's a valid department
if ($deptId == $this->getDeptId() || !($dept=Dept::lookup($deptId))) {
}
$this->dept = $dept;
return $this->save();
Peter Rotich
committed
// Set staff ID...assign/unassign/release (id can be 0)
Peter Rotich
committed
$this->staff = Staff::lookup($staffId);
return $this->save();
if ($slaId == $this->getSLAId())
return true;
$this->sla = Sla::lookup($slaId);
return $this->save();
}
/**
* Selects the appropriate service-level-agreement plan for this ticket.
* When tickets are transfered between departments, the SLA of the new
* department should be applied to the ticket. This would be useful,
* for instance, if the ticket is transferred to a different department
* which has a shorter grace period, the ticket should be considered
* overdue in the shorter window now that it is owned by the new
* department.
*
* $trump - if received, should trump any other possible SLA source.
* This is used in the case of email filters, where the SLA
* specified in the filter should trump any other SLA to be
* considered.
*/
function selectSLAId($trump=null) {
global $cfg;
# XXX Should the SLA be overridden if it was originally set via an
# email filter? This method doesn't consider such a case
if ($trump && is_numeric($trump)) {
} elseif ($this->getDept() && $this->getDept()->getSLAId()) {
} elseif ($this->getTopic() && $this->getTopic()->getSLAId()) {
$slaId = $this->getTopic()->getSLAId();
} else {
$slaId = $cfg->getDefaultSLAId();
}
return ($slaId && $this->setSLAId($slaId)) ? $slaId : false;
}
//Set team ID...assign/unassign/release (id can be 0)
if (!is_numeric($teamId))
return false;
Peter Rotich
committed
$this->team = Team::lookup($teamId);
return $this->save();
function setStatus($status, $comments='', &$errors=array(), $set_closing_agent=true) {
if ($thisstaff && !($role = $thisstaff->getRole($this->getDeptId())))
if ($status && is_numeric($status))
$status = TicketStatus::lookup($status);
if (!$status || !$status instanceof TicketStatus)
return false;
// Double check permissions (when changing status)
if ($role && $this->getStatusId()) {
switch ($status->getState()) {
case 'closed':
if (!($role->hasPerm(TicketModel::PERM_CLOSE)))
return false;
break;
case 'deleted':
// XXX: intercept deleted status and do hard delete
if ($role->hasPerm(TicketModel::PERM_DELETE))
return $this->delete($comments);
// Agent doesn't have permission to delete tickets
if ($this->getStatusId() == $status->getId())
return true;
// Perform checks on the *new* status, _before_ the status changes
// Check if ticket is closeable
$closeable = $this->isCloseable();
if ($closeable !== true)
$errors['err'] = $closeable ?: sprintf(__('%s cannot be closed'), __('This ticket'));
if ($errors)
$this->closed = $this->lastupdate = SqlFunction::NOW();
$this->duedate = null;
$ecb = function($t) use ($status) {
$t->logEvent('closed', array('status' => array($status->getId(), $status->getName())));
$t->deleteDrafts();
};
break;
case 'open':
// TODO: check current status if it allows for reopening
$this->closed = $this->lastupdate = $this->reopened = SqlFunction::NOW();
$t->logEvent('reopened', false, null, 'closed');
// If the ticket is not open then clear answered flag
if (!$this->isOpen())
default:
return false;
// Log status change b4 reload — if currently has a status. (On new
// ticket, the ticket is opened and thereafter the status is set to
// the requested status).
$alert = false;
if ($comments) {
// Send out alerts if comments are included
$alert = true;
$this->logNote(__('Status Changed'), $comments, $thisstaff, $alert);
if ($ecb)
$ecb($this);
elseif ($hadStatus)
// Don't log the initial status change
$this->logEvent('edited', array('status' => $status->getId()));
}
function setState($state, $alerts=false) {
switch (strtolower($state)) {
case 'open':
return $this->setStatus('open');
case 'closed':
return $this->setStatus('closed');
case 'answered':
return $this->setAnsweredState(1);
case 'unanswered':
return $this->setAnsweredState(0);
case 'overdue':
return $this->markOverdue();
case 'notdue':
return $this->clearOverdue();
case 'unassined':
return $this->unassign();
}
// FIXME: Throw and excception and add test cases
return false;
}
function setAnsweredState($isanswered) {
$this->isanswered = $isanswered;
return $this->save();
if (!$this->isClosed())
return false;
// Set status to open based on current closed status settings
// If the closed status doesn't have configured "reopen" status then use the
// the default ticket status.
if (!($status=$this->getStatus()->getReopenStatus()))
$status = $cfg->getDefaultTicketStatusId();
return $status ? $this->setStatus($status) : false;
}
function onNewTicket($message, $autorespond=true, $alertstaff=true) {
global $cfg;
//Log stuff here...
Peter Rotich
committed
if (!$autorespond && !$alertstaff)
return true; //No alerts to send.
/* ------ SEND OUT NEW TICKET AUTORESP && ALERTS ----------*/
Peter Rotich
committed
|| !($dept=$this->getDept())
|| !($tpl = $dept->getTemplate())
|| !($email=$dept->getAutoRespEmail())
) {
return false; //bail out...missing stuff.
$options = array();
if ($message instanceof ThreadEntry) {
$options += array(
'inreplyto'=>$message->getEmailMessageId(),
'references'=>$message->getEmailReferences(),
'thread'=>$message
);
}
else {
$options += array(
'thread' => $this->getThread(),
);
}
if ($autorespond
&& $cfg->autoRespONNewTicket()
&& $dept->autoRespONNewTicket()
&& ($msg = $tpl->getAutoRespMsgTemplate())
) {
$msg = $this->replaceVars(
$msg->asArray(),
array('message' => $message,
'recipient' => $this->getOwner(),
'signature' => ($dept && $dept->isPublic())?$dept->getSignature():''
)
);
$email->sendAutoReply($this->getOwner(), $msg['subj'], $msg['body'],
Peter Rotich
committed
// Send alert to out sleepy & idle staff.
&& $cfg->alertONNewTicket()
&& ($email=$dept->getAlertEmail())
&& ($msg=$tpl->getNewTicketAlertMsgTemplate())
) {
$msg = $this->replaceVars($msg->asArray(), array('message' => $message));
$recipients = $sentlist = array();
// Exclude the auto responding email just incase it's from staff member.
if ($message instanceof ThreadEntry && $message->isAutoReply())
$sentlist[] = $this->getEmail();
// Alert admin??
if ($cfg->alertAdminONNewTicket()) {
$alert = $this->replaceVars($msg, array('recipient' => 'Admin'));
$email->sendAlert($cfg->getAdminEmail(), $alert['subj'], $alert['body'], null, $options);
Peter Rotich
committed
// Only alerts dept members if the ticket is NOT assigned.
if ($cfg->alertDeptMembersONNewTicket() && !$this->isAssigned()) {
if ($members = $dept->getMembersForAlerts()->all())
$recipients = array_merge($recipients, $members);
Peter Rotich
committed
if ($cfg->alertDeptManagerONNewTicket() && $dept && ($manager=$dept->getManager()))
$recipients[] = $manager;
Peter Rotich
committed
// Account manager
if ($cfg->alertAcctManagerONNewMessage()
&& ($org = $this->getOwner()->getOrganization())
&& ($acct_manager = $org->getAccountManager())
) {
if ($acct_manager instanceof Team)
$recipients = array_merge($recipients, $acct_manager->getMembers());
else
$recipients[] = $acct_manager;
}
foreach ($recipients as $k=>$staff) {
if (!is_object($staff)
|| !$staff->isAvailable()
|| in_array($staff->getEmail(), $sentlist)
) {
continue;
}
$alert = $this->replaceVars($msg, array('recipient' => $staff));
$email->sendAlert($staff, $alert['subj'], $alert['body'], null, $options);
global $ost, $cfg;
//Log the limit notice as a warning for admin.
$msg=sprintf(_S('Maximum open tickets (%1$d) reached for %2$s'),
$cfg->getMaxOpenTickets(), $this->getEmail());
$ost->logWarning(sprintf(_S('Maximum Open Tickets Limit (%s)'),$this->getEmail()),
$msg);
if (!$sendNotice || !$cfg->sendOverLimitNotice())
&& ($tpl=$dept->getTemplate())
&& ($msg=$tpl->getOverlimitMsgTemplate())
&& ($email=$dept->getAutoRespEmail())
) {
$msg = $this->replaceVars(
$msg->asArray(),
array('signature' => ($dept && $dept->isPublic())?$dept->getSignature():'')
);
Peter Rotich
committed
$email->sendAutoReply($this->getOwner(), $msg['subj'], $msg['body']);
$user = $this->getOwner();
Peter Rotich
committed
// Alert admin...this might be spammy (no option to disable)...but it is helpful..I think.
$alert=sprintf(__('Maximum open tickets reached for %s.'), $this->getEmail())."\n"
.sprintf(__('Open tickets: %d'), $user->getNumOpenTickets())."\n"
.sprintf(__('Max allowed: %d'), $cfg->getMaxOpenTickets())
."\n\n".__("Notice sent to the user.");
Peter Rotich
committed
$ost->alertAdmin(__('Overlimit Notice'), $alert);
Peter Rotich
committed
$this->isanswered = 1;
$this->save();
$vars = array_merge($options,
array(
'activity' => _S('New Response'),
'threadentry' => $response
)
);
/*
* Notify collaborators on response or new message
*
*/
function notifyCollaborators($entry, $vars = array()) {
if (!$entry instanceof ThreadEntry
|| !($recipients=$this->getRecipients())
|| !($dept=$this->getDept())
|| !($tpl=$dept->getTemplate())
|| !($msg=$tpl->getActivityNoticeMsgTemplate())
|| !($email=$dept->getEmail())
) {
$skip = array();
if ($entry instanceof Message) {
$poster = $entry->getUser();
// Skip the person who sent in the message
$skip[$entry->getUserId()] = 1;
// Skip all the other recipients of the message
foreach ($entry->getAllEmailRecipients() as $R) {
foreach ($recipients as $R2) {
if (0 === strcasecmp($R2->getEmail(), $R->mailbox.'@'.$R->host)) {
$skip[$R2->getUserId()] = true;
break;
}
}
}
$poster = $entry->getStaff();
// Skip the ticket owner
$skip[$this->getUserId()] = 1;
$vars = array_merge($vars, array(
'message' => (string) $entry,
'poster' => $poster ?: _S('A collaborator'),
)
);
$msg = $this->replaceVars($msg->asArray(), $vars);
$attachments = $cfg->emailAttachments()?$entry->getAttachments():array();
$options = array('inreplyto' => $entry->getEmailMessageId(),
'thread' => $entry);
foreach ($recipients as $recipient) {
// Skip folks who have already been included on this part of
// the conversation
if (isset($skip[$recipient->getUserId()]))
continue;
$notice = $this->replaceVars($msg, array('recipient' => $recipient));
$email->send($recipient, $notice['subj'], $notice['body'], $attachments,
function onMessage($message, $autorespond=true) {
$this->isanswered = 0;
$this->lastupdate = SqlFunction::NOW();
$this->save();
Peter Rotich
committed
// Reopen if closed AND reopenable
// We're also checking autorespond flag because we don't want to
// reopen closed tickets on auto-reply from end user. This is not to
// confused with autorespond on new message setting
if ($autorespond && $this->isClosed() && $this->isReopenable()) {
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
// Auto-assign to closing staff or last respondent
// If the ticket is closed and auto-claim is not enabled then put the
// ticket back to unassigned pool.
if (!$cfg->autoClaimTickets()) {
$this->setStaffId(0);
}
elseif (!($staff = $this->getStaff()) || !$staff->isAvailable()) {
// Ticket has no assigned staff - if auto-claim is enabled then
// try assigning it to the last respondent (if available)
// otherwise leave the ticket unassigned.
if (($lastrep = $this->getLastRespondent())
&& $lastrep->isAvailable()
) {
$this->setStaffId($lastrep->getId()); //direct assignment;
}
else {
// unassign - last respondent is not available.
$this->setStaffId(0);
}
}
}
// Figure out the user
if ($this->getOwnerId() == $message->getUserId())
$user = new TicketOwner(
User::lookup($message->getUserId()), $this);
else
$user = Collaborator::lookup(array(
'user_id' => $message->getUserId(),
'thread_id' => $this->getThreadId()));
/********** double check auto-response ************/
if (!$user)
$autorespond=false;
elseif ($autorespond && (Email::getIdByEmail($user->getEmail())))
elseif ($autorespond && ($dept=$this->getDept()))
$autorespond=$dept->autoRespONNewMessage();
if (!$autorespond
|| !$cfg->autoRespONNewMessage()
|| !$message
) {
return; //no autoresp or alerts.
}
$dept = $this->getDept();
$email = $dept->getAutoRespEmail();
Peter Rotich
committed
// If enabled...send confirmation to user. ( New Message AutoResponse)
if ($email
&& ($tpl=$dept->getTemplate())
&& ($msg=$tpl->getNewMessageAutorepMsgTemplate())
) {
$msg = $this->replaceVars($msg->asArray(),
array(
'recipient' => $user,
'signature' => ($dept && $dept->isPublic())?$dept->getSignature():''
)
);
'inreplyto' => $message->getEmailMessageId(),
'thread' => $message
);
$email->sendAutoReply($user, $msg['subj'], $msg['body'],
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())
) {
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
//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->checkStaffPerm($staff))
) {
$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) {
if ($this->isClosed())
$this->reopen(); //Assigned tickets must be open - otherwise why assign?
// Assignee must be an object of type Staff or Team
if (!$assignee || !is_object($assignee))
return false;
$comments = $comments ?: _S('Ticket assignment');
$assigner = $thisstaff ?: _S('SYSTEM (Auto Assignment)');
Peter Rotich
committed
//Log an internal note - no alerts on the internal note.
if ($user_comments) {
$note = $this->logNote(
sprintf(_S('Ticket Assigned to %s'), $assignee->getName()),
$comments, $assigner, false);
}
// See if we need to send alerts
if (!$alert || !$cfg->alertONAssignment())
return true; //No alerts!
if (!$dept
|| !($tpl = $dept->getTemplate())
|| !($email = $dept->getAlertEmail())
) {
// Recipients
$recipients = array();
if ($assignee instanceof Staff) {
if ($cfg->alertStaffONAssignment())
} elseif (($assignee instanceof Team) && $assignee->alertsEnabled()) {
if ($cfg->alertTeamMembersONAssignment() && ($members=$assignee->getMembers()))
$recipients = array_merge($recipients, $members);
elseif ($cfg->alertTeamLeadONAssignment() && ($lead=$assignee->getTeamLead()))
&& ($msg=$tpl->getAssignedAlertMsgTemplate())
) {
$msg = $this->replaceVars($msg->asArray(),
array('comments' => $comments,
'assignee' => $assignee,
'assigner' => $assigner
)
);
// Send the alerts.
$sentlist = array();
$options = $note instanceof ThreadEntry
? array(
'inreplyto'=>$note->getEmailMessageId(),
'references'=>$note->getEmailReferences(),
'thread'=>$note)
: array();
foreach ($recipients as $k=>$staff) {
if (!is_object($staff)
|| !$staff->isAvailable()
|| in_array($staff->getEmail(), $sentlist)
) {
continue;
}
$alert = $this->replaceVars($msg, array('recipient' => $staff));
$email->sendAlert($staff, $alert['subj'], $alert['body'], null, $options);
function onOverdue($whine=true, $comments="") {
if ($whine && ($sla = $this->getSLA()) && !$sla->alertOnOverdue())
// Check if we need to send alerts.
if (!$whine
|| !$cfg->alertONOverdueTicket()
|| !($dept = $this->getDept())
) {
}
// Get the message template
if (($tpl = $dept->getTemplate())
&& ($msg=$tpl->getOverdueAlertMsgTemplate())
&& ($email = $dept->getAlertEmail())
) {
$msg = $this->replaceVars($msg->asArray(),
array('comments' => $comments)
);
// Recipients
$recipients = array();
// Assigned staff or team... if any
if ($this->isAssigned() && $cfg->alertAssignedONOverdueTicket()) {
if ($this->getStaffId()) {
}
elseif ($this->getTeamId()
&& ($team = $this->getTeam())
&& ($members = $team->getMembers())
) {
$recipients=array_merge($recipients, $members);
}
}
elseif ($cfg->alertDeptMembersONOverdueTicket() && !$this->isAssigned()) {
// Only alerts dept members if the ticket is NOT assigned.
if ($members = $dept->getMembersForAlerts()->all())
$recipients = array_merge($recipients, $members);
// Always alert dept manager??
if ($cfg->alertDeptManagerONOverdueTicket()
&& $dept && ($manager=$dept->getManager())
) {
}
$sentlist = array();
foreach ($recipients as $k=>$staff) {
if (!is_object($staff)
|| !$staff->isAvailable()
|| in_array($staff->getEmail(), $sentlist)
) {
continue;
}
$alert = $this->replaceVars($msg, array('recipient' => $staff));
$email->sendAlert($staff, $alert['subj'], $alert['body'], null);
Peter Rotich
committed
// TemplateVariable interface
function asVar() {
return $this->getNumber();
switch(mb_strtolower($tag)) {
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
case 'phone':
case 'phone_number':
return $this->getPhoneNumber();
break;
case 'auth_token':
return $this->getOldAuthToken();
break;
case 'client_link':
return sprintf('%s/view.php?t=%s',
$cfg->getBaseUrl(), $this->getNumber());
break;
case 'staff_link':
return sprintf('%s/scp/tickets.php?id=%d', $cfg->getBaseUrl(), $this->getId());
break;
case 'create_date':
return new FormattedDate($this->getCreateDate());
break;
case 'due_date':
if ($due = $this->getEstDueDate())
return new FormattedDate($due);
break;
case 'close_date':
if ($this->isClosed())
return new FormattedDate($this->getCloseDate());
break;
case 'last_update':
return new FormattedDate($this->last_update);
case 'user':
return $this->getOwner();
default:
if (isset($this->_answers[$tag]))
// The answer object is retrieved here which will
// automatically invoke the toString() method when the
// answer is coerced into text
return $this->_answers[$tag];
static function getVarScope() {
$base = array(
'assigned' => __('Assigned agent and/or team'),
'class' => 'FormattedDate', 'desc' => __('Date Closed'),
),
'create_date' => array(
'class' => 'FormattedDate', 'desc' => __('Date created'),
'class' => 'Dept', 'desc' => __('Department'),
'class' => 'FormattedDate', 'desc' => __('Due Date'),
'email' => __('Default email address of ticket owner'),
'name' => array(
'class' => 'PersonsName', 'desc' => __('Name of ticket owner'),
),
'number' => __('Ticket number'),
'phone' => __('Phone number of ticket owner'),
'class' => 'Priority', 'desc' => __('Priority'),
),
'recipients' => array(
'class' => 'UserList', 'desc' => __('List of all recipient names'),
'source' => __('Source'),
'class' => 'TicketStatus', 'desc' => __('Status'),
),
'staff' => array(
'class' => 'Staff', 'desc' => __('Assigned/closing agent'),
),
'subject' => 'Subject',
'team' => array(
'class' => 'Team', 'desc' => __('Assigned/closing team'),
),
'thread' => array(
'class' => 'TicketThread', 'desc' => __('Ticket Thread'),
'class' => 'Topic', 'desc' => __('Help topic'),
),
// XXX: Isn't lastreponse and lastmessage more useful
'last_update' => array(
'class' => 'FormattedDate', 'desc' => __('Time of last update'),
),
'user' => array(
'class' => 'User', 'desc' => __('Ticket owner'),
),
);
$extra = VariableReplacer::compileFormScope(TicketForm::getInstance());
return $base + $extra;
}
//Replace base variables.
function replaceVars($input, $vars = array()) {
global $ost;
$vars = array_merge($vars, array('ticket' => $this));
return $ost->replaceTemplateVariables($input, $vars);
}
function markUnAnswered() {
return (!$this->isAnswered() || $this->setAnsweredState(0));
}
function markAnswered() {
return ($this->isAnswered() || $this->setAnsweredState(1));
}
function markOverdue($whine=true) {
global $cfg;
Peter Rotich
committed
$this->isoverdue = 1;
if (!$this->save())
$this->logEvent('overdue');
Peter Rotich
committed
//NOTE: Previously logged overdue event is NOT annuled.
Peter Rotich
committed
// clear due date if it's in the past
if ($this->getDueDate() && Misc::db2gmtime($this->getDueDate()) <= Misc::gmtime())
$this->duedate = null;
// Clear SLA if est. due date is in the past
if ($this->getSLADueDate() && Misc::db2gmtime($this->getSLADueDate()) <= Misc::gmtime())
$this->sla = null;
Peter Rotich
committed
//Dept Tranfer...with alert.. done by staff
function transfer(TransferForm $form, &$errors, $alert=true) {
global $thisstaff, $cfg;
Peter Rotich
committed
// Check if staff can do the transfer
if (!$this->checkStaffPerm($thisstaff, Ticket::PERM_TRANSFER))
$cdept = $this->getDept(); // Current department
$dept = $form->getDept(); // Target department
if (!$dept || !($dept instanceof Dept))
$errors['dept'] = __('Department selection required');
elseif ($dept->getid() == $this->getDeptId())
$errors['dept'] = sprintf(
__('%s already in the department'), __('Ticket'));
else {
$this->dept_id = $dept->getId();
// Make sure the new department allows assignment to the
// currently assigned agent (if any)
if ($this->isAssigned()
&& ($staff=$this->getStaff())
&& $dept->assignMembersOnly()
&& !$dept->isMember($staff)
) {
$this->staff_id = 0;
}
}
Peter Rotich
committed
// Reopen ticket if closed
if ($this->isClosed())
$this->reopen();
// Set SLA of the new department
if (!$this->getSLAId() || $this->getSLA()->isTransient())
$this->selectSLAId();
Peter Rotich
committed
// Log transfer event
$this->logEvent('transferred');
$note = null;
$comments = $form->getField('comments')->getClean();
if ($comments) {
$title = sprintf(__('%1$s transferred from %2$s to %3$s'),
__('Ticket'),
$cdept->getName(),
$dept->getName());
Peter Rotich
committed
return true; //no alerts!!
if (($email = $dept->getAlertEmail())
&& ($tpl = $dept->getTemplate())
&& ($msg=$tpl->getTransferAlertMsgTemplate())
) {
$msg = $this->replaceVars($msg->asArray(),
// Recipients
$recipients = array();
// Assigned staff or team... if any
if($this->isAssigned() && $cfg->alertAssignedONTransfer()) {
if($this->getStaffId())
$recipients[] = $this->getStaff();
elseif ($this->getTeamId()
&& ($team=$this->getTeam())
&& ($members=$team->getMembers())
) {
$recipients = array_merge($recipients, $members);
}
}
elseif ($cfg->alertDeptMembersONTransfer() && !$this->isAssigned()) {
// Only alerts dept members if the ticket is NOT assigned.
if ($members = $dept->getMembersForAlerts()->all())
$recipients = array_merge($recipients, $members);
// Always alert dept manager??
if ($cfg->alertDeptManagerONTransfer()
&& $dept
&& ($manager=$dept->getManager())
) {
$recipients[] = $manager;
}
if ($note) {
$options += array(
'inreplyto'=>$note->getEmailMessageId(),
'references'=>$note->getEmailReferences(),
'thread'=>$note);
}
foreach ($recipients as $k=>$staff) {
if (!is_object($staff)
|| !$staff->isAvailable()
|| in_array($staff->getEmail(), $sentlist)
) {
continue;
}
$alert = $this->replaceVars($msg, array('recipient' => $staff));
$email->sendAlert($staff, $alert['subj'], $alert['body'], null, $options);