diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index beb0c56135347e2ce559add0e351e9259ee02aed..731bb1f2188db76362d5a1df3771640a1fd137b1 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -73,15 +73,16 @@ class TicketsAjaxAPI extends AjaxController { $email = $T['user__default_email__address']; $count = $T['tickets']; if ($T['number']) { - $tickets[] = array('id'=>$T['number'], 'value'=>$T['number'], + $tickets[$T['number']] = array('id'=>$T['number'], 'value'=>$T['number'], 'info'=>"{$T['number']} — {$email}", 'matches'=>$_REQUEST['q']); } else { - $tickets[] = array('email'=>$email, 'value'=>$email, + $tickets[$email] = array('email'=>$email, 'value'=>$email, 'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']); } } + $tickets = array_values($tickets); return $this->json_encode($tickets); } diff --git a/include/class.export.php b/include/class.export.php index 2ea048ae92996d72523d50f28849eb6a2cc85490..4ee0c0c796ed0e0d9f69349162ff0dac39817e3c 100644 --- a/include/class.export.php +++ b/include/class.export.php @@ -65,7 +65,6 @@ class Export { $tickets = $sql->models() ->select_related('user', 'user__default_email', 'dept', 'staff', 'team', 'staff', 'cdata', 'topic', 'status', 'cdata__:priority') - ->options(QuerySet::OPT_NOCACHE) ->annotate(array( 'collab_count' => TicketThread::objects() ->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1))) diff --git a/include/class.format.php b/include/class.format.php index 216cb6e630ea42be0d8ca88bdca19a372c33b182..2e745a592a3083f876fb53116a60153d5eb98748 100644 --- a/include/class.format.php +++ b/include/class.format.php @@ -546,6 +546,10 @@ class Format { if (!$timestamp || !($datetime = DateTime::createFromFormat('U', $timestamp))) return ''; + // Normalize timezone + if ($timezone) + $timezone = Format::timezone($timezone); + // Set the desired timezone (caching since it will be mostly same // for most date formatting. $timezone = Format::timezone($timezone, $cfg->getTimezone()); diff --git a/include/class.forms.php b/include/class.forms.php index 6a1cab27febbd54a78abe67d0422d13c5c61f02c..099c971f5fe5d4d3020c14e19d7b62d4f96b7cc1 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -2159,6 +2159,8 @@ class DatetimeField extends FormField { } function toString($value) { + if (is_array($value)) + return ''; $timestamp = is_int($value) ? $value : (int) strtotime($value); if ($timestamp <= 0) diff --git a/include/class.queue.php b/include/class.queue.php index 9a0ad18620417d0c17c45d71c524031971c80d1e..e336c2085e4e8cead73977a5b9ddf587c4c28f18 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -149,7 +149,7 @@ class CustomQueue extends VerySimpleModel { $all = $this->getSupportedMatches($this->getRoot()); $items = array(); $criteria = $criteria ?: $this->getCriteria(true); - foreach ($criteria as $C) { + foreach ($criteria ?: array() as $C) { list($path, $method, $value) = $C; if ($path === ':keywords') { $items[] = Format::htmlchars("\"{$value}\""); diff --git a/include/class.staff.php b/include/class.staff.php index 9f346df4e58dfc4189571e6d4444858a2b753b88..0deedfefc4568e579f211d098f07899ec8991822 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -598,7 +598,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable { $visibility = Q::any(new Q(array('status__state'=>'open', $assigned))); // -- Routed to a department of mine - if (!$this->showAssignedOnly() && ($depts=$this->getDepts())) { + if (($depts=$this->getDepts()) && count($depts)) { $visibility->add(array('dept_id__in' => $depts)); $visibility->add(array('thread__referrals__dept__id__in' => $depts)); } diff --git a/include/class.thread.php b/include/class.thread.php index a9485d0b85477e339e6d4fc3cbe4ae978a15abb6..f1c6ac988fd06715631d52fa03604da7108045fa 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -161,11 +161,20 @@ implements Searchable { return $collaborators; } + function isCollaborator($user) { + return $this->collaborators->findFirst(array( + 'user_id' => $user->getId(), + 'thread_id' => $this->getId())); + } + function addCollaborator($user, $vars, &$errors, $event=true) { if (!$user) return null; + if ($this->isCollaborator($user)) + return false; + $vars = array_merge(array( 'threadId' => $this->getId(), 'userId' => $user->getId()), $vars); diff --git a/include/class.ticket.php b/include/class.ticket.php index a3f33f0521c2bb510b7e6a24fd07145c6b14b577..e827b4198316879b90391e29310bd6ac15e60dff 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -2657,52 +2657,25 @@ implements RestrictedAccess, Threadable, Searchable { $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; $errors = array(); - - $hdr = Mail_parse::splitHeaders($vars['header'], true); - $existingCollab = Collaborator::getIdByUserId($vars['userId'], $this->getThreadId()); - - if (($vars['userId'] != $this->user_id) && (!$existingCollab)) { - if ($vars['userId'] == 0) { - $emailStream = '<<<EOF' . $vars['header'] . 'EOF'; - $parsed = EmailDataParser::parse($emailStream); - $email = $parsed['email']; - if (!$existinguser = User::lookupByEmail($email)) { - $name = $parsed['name']; - $user = User::fromVars(array('name' => $name, 'email' => $email)); - $vars['userId'] = $user->getId(); + if ($vars['userId'] != $this->user_id) { + if ($vars['userId']) { + $user = User::lookup($vars['userId']); + } elseif ($vars['header'] + && ($hdr= Mail_parse::splitHeaders($vars['header'], true)) + && $hdr['From'] + && ($addr= Mail_Parse::parseAddressList($hdr['From']))) { + $info = array( + 'name' => $addr[0]->personal, + 'email' => $addr[0]->mailbox.'@'.$addr[0]->host); + if ($user=User::fromVars($info)) + $vars['userId'] = $user->getId(); } - } - else - $user = User::lookup($vars['userId']); - - $c = $this->getThread()->addCollaborator($user,array(), $errors); - $addresses = array(); - foreach (array('To', 'TO', 'Cc', 'CC') as $k) { - if ($user && isset($hdr[$k]) && $hdr[$k]) - $addresses[] = Mail_Parse::parseAddressList($hdr[$k]); - } - if (count($addresses) > 1) { - $isMsg = true; - $c->setCc(); - } - } - else { - $c = Collaborator::lookup($existingCollab); - if ($c && !$c->isCc()) { - foreach (array('To', 'TO', 'Cc', 'CC') as $k) { - if (isset($hdr[$k]) && $hdr[$k]) - $addresses[] = Mail_Parse::parseAddressList($hdr[$k]); - } - if (count($addresses) > 1) { - $isMsg = true; - $c->setCc(); + if ($user) { + $c = $this->getThread()->addCollaborator($user,array(), + $errors); } - } - } - - if ($vars['userId'] == $this->user_id) - $isMsg = true; + } // Get active recipients of the response // Initial Message from Tickets created by Agent @@ -3429,7 +3402,6 @@ implements RestrictedAccess, Threadable, Searchable { return true; } - /*============== Static functions. Use Ticket::function(params); =============nolint*/ static function getIdByNumber($number, $email=null, $ticket=false) {