diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 88410826294050e92b8ef09c1f4648e231eb6a94..037d0cbd709b406771253a6feaea5b473359f8c9 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -26,46 +26,6 @@ class TicketsAjaxAPI extends AjaxController { function lookup() { global $thisstaff; - if(!is_numeric($_REQUEST['q'])) - return self::lookupByEmail(); - - - $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25; - $tickets=array(); - - $visibility = Q::any(array( - 'staff_id' => $thisstaff->getId(), - 'team_id__in' => $thisstaff->teams->values_flat('team_id'), - )); - if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts())) { - $visibility->add(array('dept_id__in' => $depts)); - } - - - $hits = TicketModel::objects() - ->filter(Q::any(array( - 'number__startswith' => $_REQUEST['q'], - ))) - ->filter($visibility) - ->values('number', 'user__emails__address') - ->annotate(array('tickets' => SqlAggregate::COUNT('ticket_id'))) - ->order_by('-created') - ->limit($limit); - - foreach ($hits as $T) { - $tickets[] = array('id'=>$T['number'], 'value'=>$T['number'], - 'info'=>"{$T['number']} — {$T['user__emails__address']}", - 'matches'=>$_REQUEST['q']); - } - if (!$tickets) - return self::lookupByEmail(); - - return $this->json_encode($tickets); - } - - function lookupByEmail() { - global $thisstaff; - $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25; $tickets=array(); @@ -80,8 +40,10 @@ class TicketsAjaxAPI extends AjaxController { $hits = TicketModel::objects() ->filter($visibility) - ->values('user__emails__address') - ->annotate(array('tickets' => SqlAggregate::COUNT('ticket_id'))) + ->values('user__default_email__address') + ->annotate(array( + 'number' => new SqlCode('null'), + 'tickets' => SqlAggregate::COUNT('ticket_id', true))) ->limit($limit); $q = $_REQUEST['q']; @@ -92,17 +54,35 @@ class TicketsAjaxAPI extends AjaxController { $hits = $ost->searcher->find($q, $hits) ->order_by(new SqlCode('__relevance__'), QuerySet::DESC); - if (!count($hits) && $q[strlen($q)-1] != '*') { + if (preg_match('/\d{2,}[^*]/', $q, $T = array())) { + $hits = TicketModel::objects() + ->values('user__default_email__address', 'number') + ->annotate(array( + 'tickets' => new SqlCode('1'), + '__relevance__' => new SqlCode(1) + )) + ->filter(array('number__startswith' => $q)) + ->limit($limit) + ->union($hits); + } + elseif (!count($hits) && $q[strlen($q)-1] != '*') { // Do wild-card fulltext search $_REQUEST['q'] = $q.'*'; - return $this->lookupByEmail(); + return $this->lookup(); } foreach ($hits as $T) { - $email = $T['user__emails__address']; + $email = $T['user__default_email__address']; $count = $T['tickets']; - $tickets[] = array('email'=>$email, 'value'=>$email, - 'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']); + if ($T['number']) { + $tickets[] = array('id'=>$T['number'], 'value'=>$T['number'], + 'info'=>"{$T['number']} — {$email}", + 'matches'=>$_REQUEST['q']); + } + else { + $tickets[] = array('email'=>$email, 'value'=>$email, + 'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']); + } } return $this->json_encode($tickets); diff --git a/include/class.search.php b/include/class.search.php index 4cf233fab8581c7a2c0e656b988750d79d460167..69391fe05808a1ff808535dfe0868adff63868ce 100644 --- a/include/class.search.php +++ b/include/class.search.php @@ -41,7 +41,7 @@ abstract class SearchBackend { ); abstract function update($model, $id, $content, $new=false, $attrs=array()); - abstract function find($query, QuerySet $criteria); + abstract function find($query, QuerySet $criteria, $addRelevance=true); static function register($backend=false) { $backend = $backend ?: get_called_class(); @@ -76,9 +76,9 @@ class SearchInterface { $this->bootstrap(); } - function find($query, QuerySet $criteria) { + function find($query, QuerySet $criteria, $addRelevance=true) { $query = Format::searchable($query); - return $this->backend->find($query, $criteria); + return $this->backend->find($query, $criteria, $addRelevance); } function update($model, $id, $content, $new=false, $attrs=array()) { @@ -324,7 +324,7 @@ class MysqlSearchBackend extends SearchBackend { return implode(' ', $results); } - function find($query, QuerySet $criteria) { + function find($query, QuerySet $criteria, $addRelevance=true) { global $thisstaff; $criteria = clone $criteria; @@ -343,10 +343,14 @@ class MysqlSearchBackend extends SearchBackend { switch ($criteria->model) { case false: case 'TicketModel': + if ($addRelevance) { + $criteria = $criteria->extra(array( + 'select' => array( + '__relevance__' => 'Z1.`relevance`', + ), + )); + } $criteria->extra(array( - 'select' => array( - '__relevance__' => 'Z1.`relevance`', - ), 'tables' => array( str_replace(array(':', '{}'), array(TABLE_PREFIX, $search), "(SELECT COALESCE(Z3.`object_id`, Z5.`ticket_id`, Z8.`ticket_id`) as `ticket_id`, {} AS `relevance` FROM `:_search` Z1 LEFT JOIN `:thread_entry` Z2 ON (Z1.`object_type` = 'H' AND Z1.`object_id` = Z2.`id`) LEFT JOIN `:thread` Z3 ON (Z2.`thread_id` = Z3.`id` AND Z3.`object_type` = 'T') LEFT JOIN `:ticket` Z5 ON (Z1.`object_type` = 'T' AND Z1.`object_id` = Z5.`ticket_id`) LEFT JOIN `:user` Z6 ON (Z6.`id` = Z1.`object_id` and Z1.`object_type` = 'U') LEFT JOIN `:organization` Z7 ON (Z7.`id` = Z1.`object_id` AND Z7.`id` = Z6.`org_id` AND Z1.`object_type` = 'O') LEFT JOIN :ticket Z8 ON (Z8.`user_id` = Z6.`id`) WHERE {}) Z1"),