diff --git a/account.php b/account.php index 18231ab48938671748b561d05611239e27fe86f5..416cd4761dda9d5b9f851dd40b58a8877bf7c598 100644 --- a/account.php +++ b/account.php @@ -52,7 +52,6 @@ if ($user && $_POST) { if (!$errors && $user->updateInfo($_POST, $errors)) Http::redirect('tickets.php'); } - elseif ($_POST) { $user_form = UserForm::getUserForm()->getForm($_POST); if ($thisclient) { @@ -81,12 +80,12 @@ elseif ($_POST) { $errors['email'] = sprintf(__('%s is a required field'), $user_form->getField('email')->getLocal('label')); elseif (!$user_form->getField('name')->getClean()) $errors['name'] = sprintf(__('%s is a required field'), $user_form->getField('name')->getLocal('label')); + // Registration for existing users + elseif ($addr && !($user = User::lookupByEmail($addr))) + $errors['err'] = __('Unable to register account. See messages below'); // Users created from ClientCreateRequest elseif (isset($_POST['backend']) && !($user = User::fromVars($user_form->getClean()))) $errors['err'] = __('Unable to create local account. See messages below'); - // Registration for existing users - elseif (!$user && !$thisclient && !($user = User::fromVars($user_form->getClean()))) - $errors['err'] = __('Unable to register account. See messages below'); // New users and users registering from a ticket access link elseif (!$user && !($user = $thisclient ?: User::fromForm($user_form))) $errors['err'] = __('Unable to register account. See messages below'); diff --git a/include/ajax.content.php b/include/ajax.content.php index 48cb6f2b012bfbd92d32dea39bbaf582f1b9de6a..38112a11502ec5e80fb61aa2f1f039bc0f889928 100644 --- a/include/ajax.content.php +++ b/include/ajax.content.php @@ -101,7 +101,6 @@ class ContentAjaxAPI extends AjaxController { <tr><td>.lastmessage</td><td>'.__('Last Message').'</td></tr> <tr><td colspan="2" style="padding:5px 0 5px 0;"><em><b>'.__('Thread Entry expansions').'</b></em></td></tr> <tr><td>.poster</td><td>'.__('Poster').'</td></tr> - <tr><td>.posterType</td><td>'.__('Can be User or Agent').'</td></tr> <tr><td>.create_date</td><td>'.__('Date Created').'</td></tr> </table> </td> diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 643d8b4613ad80ee89da610c33843bca7b3d6610..05cf5354c426092df2d32adc814e83b31aac228a 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -652,6 +652,66 @@ function refer($tid, $target=null) { } + function release($tid) { + global $thisstaff; + + if (!($ticket=Ticket::lookup($tid))) + Http::response(404, __('No such ticket')); + + if (!$ticket->checkStaffPerm($thisstaff, Ticket::PERM_RELEASE) && !$thisstaff->isManager()) + Http::response(403, __('Permission denied')); + + if (!$ticket->isAssigned()) + $errors['err'] = __('Ticket is not assigned!'); + + + $errors = array(); + $info = array(':title' => sprintf(__('Ticket #%s: %s'), + $ticket->getNumber(), + __('Release Confirmation'))); + + $form = ReleaseForm::instantiate($_POST); + $hasData = ($_POST['sid'] || $_POST['tid']); + + $staff = $ticket->getStaff(); + $team = $ticket->getTeam(); + if ($_POST) { + if ($hasData && $ticket->release($_POST, $errors)) { + $data = array(); + + if ($staff && !$ticket->getStaff()) + $data['staff'] = array($staff->getId(), (string) $staff->getName()->getOriginal()); + if ($team && !$ticket->getTeam()) + $data['team'] = $team->getId(); + $ticket->logEvent('released', $data); + + $comments = $form->getComments(); + if ($comments) { + $title = __('Assignment Released'); + $_errors = array(); + + $ticket->postNote( + array('note' => $comments, 'title' => $title), + $_errors, $thisstaff, false); + } + + $_SESSION['::sysmsgs']['msg'] = __('Ticket assignment released successfully'); + Http::response(201, $ticket->getId()); + } + + if (!$hasData) + $errors['err'] = __('Please check an assignee to release assignment'); + + $form->addErrors($errors); + $info['error'] = $errors['err'] ?: __('Unable to release ticket assignment'); + } + + if($errors && $errors['err']) + $info['error'] = $errors['err'] ?: __('Unable to release ticket'); + + include STAFFINC_DIR . 'templates/release.tmpl.php'; + } + function massProcess($action, $w=null) { global $thisstaff, $cfg; diff --git a/include/class.dept.php b/include/class.dept.php index 384a749a23b86c9d9a237fb383060fec52fc22be..387e8f7fa4fb4e8a6802a18e49951a49d2ef33c2 100644 --- a/include/class.dept.php +++ b/include/class.dept.php @@ -786,6 +786,7 @@ implements TemplateVariable, Searchable { $this->group_membership = $vars['group_membership']; $this->ticket_auto_response = isset($vars['ticket_auto_response'])?$vars['ticket_auto_response']:1; $this->message_auto_response = isset($vars['message_auto_response'])?$vars['message_auto_response']:1; + $this->flags = $vars['flags'] ?: 0; $this->setFlag(self::FLAG_ASSIGN_MEMBERS_ONLY, isset($vars['assign_members_only'])); $this->setFlag(self::FLAG_DISABLE_AUTO_CLAIM, isset($vars['disable_auto_claim'])); @@ -812,7 +813,6 @@ implements TemplateVariable, Searchable { $this->setFlag(self::FLAG_ARCHIVED, true); } - $this->flags = 0; $this->setFlag(self::FLAG_DISABLE_AUTO_CLAIM, isset($vars['disable_auto_claim'])); switch ($vars['assignment_flag']) { diff --git a/include/class.email.php b/include/class.email.php index 34d1f542e7660c3e049296ff5d7f4b55c3d97021..4c338f50e076c16ed465987cf5d91e7e6ca406bd 100644 --- a/include/class.email.php +++ b/include/class.email.php @@ -118,7 +118,9 @@ class Email extends VerySimpleModel { function getInfo() { $base = $this->getHashtable(); - $base['mail_proto'] = $this->mail_proto; + $base['mail_proto'] = $this->mail_protocol; + if ($this->mail_encryption != 'NONE') + $base['mail_proto'] .= "/{$this->mail_encryption}"; return $base; } @@ -395,16 +397,16 @@ class Email extends VerySimpleModel { $this->userid = $vars['userid']; $this->mail_active = $vars['mail_active']; $this->mail_host = $vars['mail_host']; - $this->mail_protocol = $vars['mail_protocol']?$vars['mail_protocol']:'POP'; + $this->mail_protocol = $vars['mail_protocol'] ?: 'POP'; $this->mail_encryption = $vars['mail_encryption']; - $this->mail_port = $vars['mail_port']?$vars['mail_port']:0; - $this->mail_fetchfreq = $vars['mail_fetchfreq']?$vars['mail_fetchfreq']:0; - $this->mail_fetchmax = $vars['mail_fetchmax']?$vars['mail_fetchmax']:0; + $this->mail_port = $vars['mail_port'] ?: 0; + $this->mail_fetchfreq = $vars['mail_fetchfreq'] ?: 0; + $this->mail_fetchmax = $vars['mail_fetchmax'] ?: 0; $this->smtp_active = $vars['smtp_active']; $this->smtp_host = $vars['smtp_host']; - $this->smtp_port = $vars['smtp_port']?$vars['smtp_port']:0; + $this->smtp_port = $vars['smtp_port'] ?: 0; $this->smtp_auth = $vars['smtp_auth']; - $this->smtp_spoofing = isset($vars['smtp_spoofing'])?1:0; + $this->smtp_spoofing = isset($vars['smtp_spoofing']) ? 1 : 0; $this->notes = Format::sanitize($vars['notes']); //Post fetch email handling... diff --git a/include/class.forms.php b/include/class.forms.php index e13f5f15d41a0c28bebb7d7e8a1108a247d4d241..6f28d71f98dbf476523733f75c87bcaf3b5251fd 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -4928,6 +4928,49 @@ class ClaimForm extends AssignmentForm { } +class ReleaseForm extends Form { + static $id = 'unassign'; + + function getFields() { + if ($this->fields) + return $this->fields; + + $fields = array( + 'comments' => new TextareaField(array( + 'id' => 1, 'label'=> '', 'required'=>false, 'default'=>'', + 'configuration' => array( + 'html' => true, + 'size' => 'small', + 'placeholder' => __('Optional reason for releasing assignment'), + ), + ) + ), + ); + + + $this->setFields($fields); + + return $this->fields; + } + + function getField($name) { + if (($fields = $this->getFields()) + && isset($fields[$name])) + return $fields[$name]; + } + + function isValid($include=false) { + if (!parent::isValid($include)) + return false; + + return !$this->errors(); + } + + function getComments() { + return $this->getField('comments')->getClean(); + } +} + class ReferralForm extends Form { static $id = 'refer'; diff --git a/include/class.report.php b/include/class.report.php index c39ec47cc5ea595aaddcaf46d25323929d58c1cc..12d7322d3dbc6665fed18b86d8b738d49eb091ba 100644 --- a/include/class.report.php +++ b/include/class.report.php @@ -153,6 +153,9 @@ class OverviewReport { 'annulled' => 0, ), )) + ->filter(array( + 'timestamp__range' => array($start, $stop, true), + )) ->aggregate(array( 'ServiceTime' => SqlAggregate::AVG(SqlFunction::timestampdiff( new SqlCode('HOUR'), new SqlField('thread__events__timestamp'), new SqlField('timestamp')) diff --git a/include/class.thread.php b/include/class.thread.php index 5545b2db6d1f7c8978602087f37a5f95cbc8d5f6..177c608a0f66f6a9461ee00e3a01ce8f4815ffa3 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -760,7 +760,6 @@ implements TemplateVariable { var $_actions; var $is_autoreply; var $is_bounce; - var $_posterType; static protected $perms = array( self::PERM_EDIT => array( @@ -838,13 +837,6 @@ implements TemplateVariable { return $this->poster; } - function getPosterType() { - $this->staff_id ? - $this->posterType = __('Agent') : $this->posterType = __('User'); - - return $this->posterType; - } - function getTitle() { return $this->title; } @@ -1871,6 +1863,7 @@ class ThreadEvent extends VerySimpleModel { // Valid events for database storage const ASSIGNED = 'assigned'; + const RELEASED = 'released'; const CLOSED = 'closed'; const CREATED = 'created'; const COLLAB = 'collab'; @@ -1906,6 +1899,7 @@ class ThreadEvent extends VerySimpleModel { function getIcon() { $icons = array( 'assigned' => 'hand-right', + 'released' => 'unlock', 'collab' => 'group', 'created' => 'magic', 'overdue' => 'time', @@ -2092,7 +2086,7 @@ class ThreadEvents extends InstrumentedList { * $object - Object to log activity for * $state - State name of the activity (one of 'created', 'edited', * 'deleted', 'closed', 'reopened', 'error', 'collab', 'resent', - * 'assigned', 'transferred') + * 'assigned', 'released', 'transferred') * $data - (array?) Details about the state change * $user - (string|User|Staff) user triggering the state change * $annul - (state) a corresponding state change that is annulled by @@ -2175,6 +2169,30 @@ class AssignmentEvent extends ThreadEvent { } } +class ReleaseEvent extends ThreadEvent { + static $icon = 'unlock'; + static $state = 'released'; + + function getDescription($mode=self::MODE_STAFF) { + $data = $this->getData(); + switch (true) { + case isset($data['staff'], $data['team']): + $desc = __('Ticket released from <strong>{<Team>data.team}</strong> and <strong>{<Staff>data.staff}</strong> by <b>{somebody}</b> {timestamp}'); + break; + case isset($data['staff']): + $desc = __('Ticket released from <strong>{<Staff>data.staff}</strong> by <b>{somebody}</b> {timestamp}'); + break; + case isset($data['team']): + $desc = __('Ticket released from <strong>{<Team>data.team}</strong> by <b>{somebody}</b> {timestamp}'); + break; + default: + $desc = __('<b>{somebody}</b> released ticket assignment {timestamp}'); + break; + } + return $this->template($desc); + } +} + class ReferralEvent extends ThreadEvent { static $icon = 'exchange'; static $state = 'referred'; diff --git a/include/class.ticket.php b/include/class.ticket.php index 5b276e7e8a4e2e275d7e05257045723741f1f1c7..f9646b39df8096adb8c07a48c1b8de681c143cb5 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -98,7 +98,9 @@ implements RestrictedAccess, Threadable, Searchable { const PERM_CREATE = 'ticket.create'; const PERM_EDIT = 'ticket.edit'; const PERM_ASSIGN = 'ticket.assign'; + const PERM_RELEASE = 'ticket.release'; const PERM_TRANSFER = 'ticket.transfer'; + const PERM_REFER = 'ticket.refer'; const PERM_REPLY = 'ticket.reply'; const PERM_CLOSE = 'ticket.close'; const PERM_DELETE = 'ticket.delete'; @@ -119,11 +121,21 @@ implements RestrictedAccess, Threadable, Searchable { /* @trans */ 'Assign', 'desc' => /* @trans */ 'Ability to assign tickets to agents or teams'), + self::PERM_RELEASE => array( + 'title' => + /* @trans */ 'Release', + 'desc' => + /* @trans */ 'Ability to release ticket assignment'), self::PERM_TRANSFER => array( 'title' => /* @trans */ 'Transfer', 'desc' => /* @trans */ 'Ability to transfer tickets between departments'), + self::PERM_REFER => array( + 'title' => + /* @trans */ 'Refer', + 'desc' => + /* @trans */ 'Ability to manage ticket referrals'), self::PERM_REPLY => array( 'title' => /* @trans */ 'Post Reply', @@ -2493,8 +2505,15 @@ implements RestrictedAccess, Threadable, Searchable { return true; } - function release() { - return $this->unassign(); + function release($info=array(), &$errors) { + if ($info['sid'] && $info['tid']) + return $this->unassign(); + elseif ($info['sid'] && $this->setStaffId(0)) + return true; + elseif ($info['tid'] && $this->setTeamId(0)) + return true; + + return false; } function refer(ReferralForm $form, &$errors, $alert=true) { @@ -4034,7 +4053,7 @@ implements RestrictedAccess, Threadable, Searchable { // department if ($vars['assignId'] && !( $role - ? $role->hasPerm(Ticket::PERM_ASSIGN) + ? ($role->hasPerm(Ticket::PERM_ASSIGN) || $role->__new__) : $thisstaff->hasPerm(Ticket::PERM_ASSIGN, false) )) { $errors['assignId'] = __('Action Denied. You are not allowed to assign/reassign tickets.'); @@ -4103,12 +4122,6 @@ implements RestrictedAccess, Threadable, Searchable { $attachments = $attachments->merge($response->getAttachments()); } - $message = (string) $message; - if ($response) { - $message .= ($cfg->isRichTextEnabled()) ? "<br><br>" : "\n\n"; - $message .= $response->getBody(); - } - if ($vars['signature']=='mine') $signature=$thisstaff->getSignature(); elseif ($vars['signature']=='dept' && $dept && $dept->isPublic()) @@ -4120,7 +4133,7 @@ implements RestrictedAccess, Threadable, Searchable { array( 'message' => $message, 'signature' => $signature, - 'response' => ($response) ? $response->getBody() : '', + 'response' => $response ?: '', 'recipient' => $ticket->getOwner(), //End user 'staff' => $thisstaff, ) diff --git a/include/class.user.php b/include/class.user.php index 2fd1ad78a42a2f057c3de449f171993f1d03681a..4681b3fd1a8aa596bead9462a87a2cfcd2e2a1dc 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -1192,16 +1192,10 @@ class UserAccount extends VerySimpleModel { } /* - * This assumes the staff is doing the update + * Updates may be done by Staff or by the User if registration + * options are set to Public */ function update($vars, &$errors) { - global $thisstaff; - - - if (!$thisstaff) { - $errors['err'] = __('Access denied'); - return false; - } // TODO: Make sure the username is unique diff --git a/include/i18n/en_US/role.yaml b/include/i18n/en_US/role.yaml index ca76b2650513d4ffcf0d5bb48fa57cb07b203757..ec0832d8d33dd6a27f4e0c3cca1ffa4e46c00d02 100644 --- a/include/i18n/en_US/role.yaml +++ b/include/i18n/en_US/role.yaml @@ -20,7 +20,9 @@ ticket.create, ticket.edit, ticket.assign, + ticket.release, ticket.transfer, + ticket.refer, ticket.reply, ticket.close, ticket.delete, @@ -44,7 +46,9 @@ ticket.create, ticket.edit, ticket.assign, + ticket.release, ticket.transfer, + ticket.refer, ticket.reply, ticket.close, task.create, @@ -64,7 +68,9 @@ permissions: [ ticket.create, ticket.assign, + ticket.release, ticket.transfer, + ticket.refer, ticket.reply task.create, task.assign, diff --git a/include/i18n/en_US/templates/email/ticket.notice.yaml b/include/i18n/en_US/templates/email/ticket.notice.yaml index bf2a6803c92eb299792264774f933620dc8f9d5c..9cfbefb809692e33b99eef05a01d305e370293a1 100644 --- a/include/i18n/en_US/templates/email/ticket.notice.yaml +++ b/include/i18n/en_US/templates/email/ticket.notice.yaml @@ -26,6 +26,9 @@ body: | %{message} <br> <br> + %{response} + <br> + <br> If need be, a representative will follow-up with you as soon as possible. You can also <a href="%{recipient.ticket_link}">view this ticket's progress online</a>. diff --git a/include/staff/dashboard.inc.php b/include/staff/dashboard.inc.php index 8bf11959560114bc18514d9d494aa3312e35d8d7..3c91e3c5fd9135cb550a2c39de52c4a0411445db 100644 --- a/include/staff/dashboard.inc.php +++ b/include/staff/dashboard.inc.php @@ -75,11 +75,11 @@ $plots = $report->getPlotData(); $date = str_ireplace('FROM_UNIXTIME(', '',$date); $date = str_ireplace(')', '',$date); $date = new DateTime('@'.$date); - if ($thisstaff->getTimezone()) - $date->setTimeZone(new DateTimeZone($thisstaff->getTimezone())); + $date->setTimeZone(new DateTimeZone($cfg->getTimezone())); + $timezone = $date->format('e'); $range[] = $date->format('F j, Y'); } - echo __($range[0] . ' - ' . $range[1]); + echo __($range[0] . ' - ' . $range[1] . ' (' . Format::timezone($timezone) . ')'); ?> <ul class="clean tabs"> diff --git a/include/staff/templates/release.tmpl.php b/include/staff/templates/release.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..a60fe50a52dd01efc87c27419590a4991da552ba --- /dev/null +++ b/include/staff/templates/release.tmpl.php @@ -0,0 +1,89 @@ +<?php +global $cfg; + +$assignees = array(); +if (($staff = $ticket->getStaff())) + $assignees[] = $staff; +if (($team = $ticket->getTeam())) + $assignees[] = $team; + +$form = ReleaseForm::instantiate($_POST); +?> +<h3 class="drag-handle"><?php echo $info[':title'] ?: __('Release Confirmation'); ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} elseif ($info['notice']) { + echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>', + $info['notice']); +} +?> +<form class="mass-action" method="post" + action="#tickets/<?php echo $ticket->getId(); ?>/release" + name="release"> + <input type='hidden' name='do' value='release'> + <table width="100%"> + <tbody> + <?php if ($staff && $team) { ?> + <tr><td> + <p> + <?php echo __('Please check assignee(s) to release assignment.'); ?> + </p> + </td></tr> + <?php } ?> + <?php if(count($assignees) > 1) { ?> + <?php foreach($assignees as $assignee) { ?> + <tr><td> + <label class="inline checkbox"> + <?php echo sprintf( + ($isStaff = $assignee instanceof Staff) + ? '<input type="checkbox" name="sid[]" id="s%d" value="%d">' + : '<input type="checkbox" name="tid[]" id="t%d" value="%d">', + $assignee->getId(), + $assignee->getId()); ?> + </label> + <?php echo '<i class="icon-'.(($isStaff) ? 'user' : 'group').'"></i>'; ?> + <?php echo $assignee->getName(); ?> + </td></tr> + <?php } ?> + <?php } else { ?> + <tr><td> + <input type="hidden" name="<?php echo (($staff)?'s':'t').'id[]'; ?>" value="()"> + <p> + <?php echo __('Please confirm to continue.'); ?> + </p> + <p> + <?php echo sprintf( + __('Are you sure you want to <b>unassign</b> ticket from <b>%s</b>?'), + ($staff) ?: $team); ?> + </p> + </td></tr> + <?php } ?> + <tr><td> + <p> + <?php print $form->getField('comments')->render(); ?> + </p> + </td></tr> + </tbody> + </table> + <hr> + <p class="full-width"> + <span class="buttons pull-left"> + <input type="reset" value="<?php echo __('Reset'); ?>"> + <input type="button" name="cancel" class="close" + value="<?php echo __('Cancel'); ?>"> + </span> + <span class="buttons pull-right"> + <input type="submit" value="<?php + echo __('Release'); ?>"> + </span> + </p> +</form> +<div class="clear"></div> diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index 8e4a8e8f8fc3cbee7480a8f5116ffc44e376ff8b..96ee98bbdeac440975ad94301eae6b2959c16569 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -162,6 +162,9 @@ if ($_POST) <br/><span class="error"><?php echo $errors['ccs']; ?></span> </td> </tr> + <?php + if ($cfg->notifyONNewStaffTicket()) { + ?> <tr class="no_border"> <td> <?php echo __('Ticket Notice');?>: @@ -174,6 +177,7 @@ if ($_POST) </select> </td> </tr> + <?php } ?> </table> </td> </tr> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index f63259ac5e03a834303b66bd4b594c8b4a4c19f3..e16900e2516aa8e42b4530bd912e0c282b986ac2 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -20,6 +20,8 @@ if (!$lock && $cfg->getTicketLockMode() == Lock::MODE_ON_VIEW) $lock = $ticket->acquireLock($thisstaff->getId()); $mylock = ($lock && $lock->getStaffId() == $thisstaff->getId()) ? $lock : null; $id = $ticket->getId(); //Ticket ID. +$isManager = $dept->isManager($thisstaff); //Check if Agent is Manager +$canRelease = ($isManager || $role->hasPerm(Ticket::PERM_RELEASE)); //Check if Agent can release tickets //Useful warnings and errors the user might want to know! if ($ticket->isClosed() && !$ticket->isReopenable()) @@ -146,14 +148,14 @@ if($ticket->isOverdue()) <?php } - if($ticket->isOpen() && ($dept && $dept->isManager($thisstaff))) { - - if($ticket->isAssigned()) { ?> - <li><a class="confirm-action" id="ticket-release" href="#release"><i class="icon-user"></i> <?php - echo __('Release (unassign) Ticket'); ?></a></li> - <?php - } - + if ($ticket->isAssigned() && $canRelease) { ?> + <li><a href="#tickets/<?php echo $ticket->getId(); + ?>/release" class="ticket-action" + data-redirect="tickets.php?id=<?php echo $ticket->getId(); ?>" > + <i class="icon-unlock"></i> <?php echo __('Release (unassign) Ticket'); ?></a></li> + <?php + } + if($ticket->isOpen() && $isManager) { if(!$ticket->isOverdue()) { ?> <li><a class="confirm-action" id="ticket-overdue" href="#overdue"><i class="icon-bell"></i> <?php echo __('Mark as Overdue'); ?></a></li> @@ -172,7 +174,7 @@ if($ticket->isOverdue()) } ?> <?php - if ($role->hasPerm(Ticket::PERM_TRANSFER)) { ?> + if ($role->hasPerm(Ticket::PERM_REFER)) { ?> <li><a href="#tickets/<?php echo $ticket->getId(); ?>/referrals" class="ticket-action" data-redirect="tickets.php?id=<?php echo $ticket->getId(); ?>" > diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig index 5c4c675cad5ffbfde918a49029645fc955d772dd..fbebb45e63ee1f85f4388d1ead81fa6b7403dd4f 100644 --- a/include/upgrader/streams/core.sig +++ b/include/upgrader/streams/core.sig @@ -1 +1 @@ -70921d5c3920ab240b08bdd55bc894c8 +26fd79dc5443f37779f9d2c4108058f4 diff --git a/include/upgrader/streams/core/0ca85857-86707325.patch.sql b/include/upgrader/streams/core/0ca85857-86707325.patch.sql index f36be800d15931cf913362e085e51b27ab870f83..2962d23e40f284614bd877ee0317e1183f7a21bf 100644 --- a/include/upgrader/streams/core/0ca85857-86707325.patch.sql +++ b/include/upgrader/streams/core/0ca85857-86707325.patch.sql @@ -3,7 +3,7 @@ * @version v1.11.0 * @title Add ticket referral * - * This patch adds a table for thread referral as well as thread event states of reffered and deleted + * This patch adds a table for thread referral as well as thread event states of referred and deleted */ CREATE TABLE `%TABLE_PREFIX%thread_referral` ( @@ -18,7 +18,7 @@ CREATE TABLE `%TABLE_PREFIX%thread_referral` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `%TABLE_PREFIX%thread_event` - CHANGE `state` `state` enum('created','closed','reopened','assigned','transferred', 'reffered', 'overdue','edited','viewed','error','collab','resent', 'deleted') NOT NULL; + CHANGE `state` `state` enum('created','closed','reopened','assigned','transferred', 'referred', 'overdue','edited','viewed','error','collab','resent', 'deleted') NOT NULL; -- Finished with patch diff --git a/include/upgrader/streams/core/70921d5c-26fd79dc.patch.sql b/include/upgrader/streams/core/70921d5c-26fd79dc.patch.sql new file mode 100644 index 0000000000000000000000000000000000000000..ed631e92d16085eecee64e084327d78ab0f56be4 --- /dev/null +++ b/include/upgrader/streams/core/70921d5c-26fd79dc.patch.sql @@ -0,0 +1,31 @@ +/** +* @signature 26fd79dc5443f37779f9d2c4108058f4 +* @version v1.11.0 +* @title Final Revisions +* +* This patch is for final revisions needed for v1.11 +*/ + +ALTER TABLE `%TABLE_PREFIX%thread_event` + CHANGE `state` `state` enum('created','closed','reopened','assigned', 'released', 'transferred', 'referred', 'overdue','edited','viewed','error','collab','resent', 'deleted') NOT NULL; + +ALTER TABLE `%TABLE_PREFIX%attachment` + ADD INDEX `file_object` (`file_id`,`object_id`); + +UPDATE `%TABLE_PREFIX%role` + SET `permissions` = REPLACE(`permissions`, '"ticket.transfer":1,', '"ticket.transfer":1,"ticket.refer":1,') + WHERE `permissions` IS NOT NULL; + +UPDATE `%TABLE_PREFIX%role` + SET `permissions` = REPLACE(`permissions`, '"ticket.assign":1,', '"ticket.assign":1,"ticket.release":1,') + WHERE `permissions` IS NOT NULL AND `permissions` LIKE '%"ticket.assign":1,%'; + +-- Ticket Notice Template +UPDATE `%TABLE_PREFIX%email_template` + SET `code_name` = REPLACE('ticket.notice', '%{message}', '%{message}<br><br>%{response}') + WHERE `code_name` = 'ticket.notice'; + + -- Finished with patch +UPDATE `%TABLE_PREFIX%config` + SET `value` = '26fd79dc5443f37779f9d2c4108058f4', `updated` = NOW() + WHERE `key` = 'schema_signature' AND `namespace` = 'core'; diff --git a/scp/ajax.php b/scp/ajax.php index 7dc4a56a2a9c690add163d05fed948045ad7cd2a..dfdb7499e7ae093c1a55e20f8937772d6447002e 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -167,6 +167,7 @@ $dispatcher = patterns('', url('^(?P<tid>\d+)/field/(?P<fid>\d+)/edit$', 'editField'), url('^(?P<tid>\d+)/field/(?P<field>\w+)/edit$', 'editField'), url('^(?P<tid>\d+)/assign(?:/(?P<to>\w+))?$', 'assign'), + url('^(?P<tid>\d+)/release$', 'release'), url('^(?P<tid>\d+)/refer(?:/(?P<to>\w+))?$', 'refer'), url('^(?P<tid>\d+)/referrals$', 'referrals'), url('^(?P<tid>\d+)/claim$', 'claim'), diff --git a/scp/tickets.php b/scp/tickets.php index 07d34243ffe3367aa0f0bde6db2b2707a49ceec6..444275482087101137b03c913c6a72957efe1d64 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -43,8 +43,11 @@ if (!$ticket) { $queue_id = null; // Search for user - if (isset($_GET['uid'])) - $user = User::lookup($_GET['uid']); + if (isset($_REQUEST['uid'])) + $user = User::lookup($_REQUEST['uid']); + + if (isset($_REQUEST['email'])) + $user = User::lookupByEmail($_REQUEST['email']); if ($user && $_GET['a'] !== 'open' @@ -283,19 +286,6 @@ if($_POST && !$errors): break; case 'process': switch(strtolower($_POST['do'])): - case 'release': - if(!$ticket->isAssigned() || !($assigned=$ticket->getAssigned())) { - $errors['err'] = __('Ticket is not assigned!'); - } elseif($ticket->release()) { - $msg=sprintf(__( - /* 1$ is the current assignee, 2$ is the agent removing the assignment */ - 'Ticket released (unassigned) from %1$s by %2$s'), - $assigned, $thisstaff->getName()); - $ticket->logActivity(__('Ticket unassigned'),$msg); - } else { - $errors['err'] = sprintf('%s %s', __('Problems releasing the ticket.'), __('Please try again!')); - } - break; case 'claim': if(!$role->hasPerm(Ticket::PERM_EDIT)) { $errors['err'] = __('Permission Denied. You are not allowed to assign/claim tickets.'); @@ -412,7 +402,7 @@ if($_POST && !$errors): } else { $vars = $_POST; - if ($vars['uid'] && (!User::lookup($vars['uid']))) + if ($vars['uid'] && !($user=User::lookup($vars['uid']))) $vars['uid'] = 0; $vars['cannedattachments'] = $response_form->getField('attachments')->getClean(); diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql index 5c1ddc7ea1a46c736dd7d05f2037925a1f75131f..fbbb6e45050facca4ad2c6390657073d14b23c96 100644 --- a/setup/inc/streams/core/install-mysql.sql +++ b/setup/inc/streams/core/install-mysql.sql @@ -25,7 +25,8 @@ CREATE TABLE `%TABLE_PREFIX%attachment` ( `inline` tinyint(1) unsigned NOT NULL DEFAULT '0', `lang` varchar(16), PRIMARY KEY (`id`), - UNIQUE KEY `file-type` (`object_id`,`file_id`,`type`) + UNIQUE KEY `file-type` (`object_id`,`file_id`,`type`), + UNIQUE KEY `file_object` (`file_id`,`object_id`) ) DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `%TABLE_PREFIX%faq`; @@ -718,7 +719,7 @@ CREATE TABLE `%TABLE_PREFIX%thread_event` ( `team_id` int(11) unsigned NOT NULL, `dept_id` int(11) unsigned NOT NULL, `topic_id` int(11) unsigned NOT NULL, - `state` enum('created','closed','reopened','assigned','transferred', 'reffered', 'overdue','edited','viewed','error','collab','resent', 'deleted') NOT NULL, + `state` enum('created','closed','reopened','assigned','released','transferred', 'referred', 'overdue','edited','viewed','error','collab','resent', 'deleted') NOT NULL, `data` varchar(1024) DEFAULT NULL COMMENT 'Encoded differences', `username` varchar(128) NOT NULL default 'SYSTEM', `uid` int(11) unsigned DEFAULT NULL, diff --git a/tickets.php b/tickets.php index 5795925f4bdffdb051dabd64b2f033da0cbb2d4c..fa88e5e55775b4aeff32dda04841b35eed6fc178 100644 --- a/tickets.php +++ b/tickets.php @@ -62,8 +62,10 @@ if ($_POST && is_object($ticket) && $ticket->getId()) { $changes += $f->getChanges(); $f->save(); } - if ($changes) - $ticket->logEvent('edited', array('fields' => $changes)); + if ($changes) { + $user = User::lookup($thisclient->getId()); + $ticket->logEvent('edited', array('fields' => $changes), $user); + } $_REQUEST['a'] = null; //Clear edit action - going back to view. } break;