diff --git a/include/ajax.search.php b/include/ajax.search.php index 0ef01784bde6a313007dcffbcc13b279e2bb03a7..f0933380e0505e8417fbeb9cf32a49f3d672b477 100644 --- a/include/ajax.search.php +++ b/include/ajax.search.php @@ -22,7 +22,7 @@ require_once(INCLUDE_DIR.'class.ajax.php'); class SearchAjaxAPI extends AjaxController { - function getAdvancedSearchDialog() { + function getAdvancedSearchDialog($key=false, $context='advsearch') { global $thisstaff; if (!$thisstaff) @@ -31,7 +31,14 @@ class SearchAjaxAPI extends AjaxController { $search = SavedSearch::create(array( 'root' => 'T', )); - $search->config = $_SESSION['advsearch']; + if (isset($_SESSION[$context])) { + // Use the most recent search + if (!$key) { + reset($_SESSION[$context]); + $key = key($_SESSION[$context]); + } + $search->config = $_SESSION[$context][$key]; + } $this->_tryAgain($search, $search->getForm()); } @@ -98,7 +105,39 @@ class SearchAjaxAPI extends AjaxController { if ($this->_hasErrors($search, $form)) return false; - $_SESSION[$key] = $search->isolateCriteria($form->getClean()); + if ($key) { + $keep = array(); + // Add in new search to the list of recent searches + $criteria = $search->isolateCriteria($form->getClean()); + $token = $this->_hashCriteria($criteria); + $keep[$token] = $criteria; + // Keep the last 5 recent searches looking from the beginning of + // the recent search list + if (isset($_SESSION[$key])) { + reset($_SESSION[$key]); + while (count($keep) < 5) { + list($k, $v) = each($_SESSION[$key]); + if (!$k) + break; + $keep[$k] = $v; + } + } + $_SESSION[$key] = $keep; + } + } + + function _hashCriteria($criteria, $size=10) { + $parts = array(); + foreach ($criteria as $C) { + list($name, $method, $value) = $C; + if (is_array($value)) + $value = implode('+', $value); + $parts[] = "{$name} {$method} {$value}"; + } + $hash = sha1(implode(' ', $parts), true); + return substr( + str_replace(array('+','/','='), '', base64_encode($hash)), + -$size); } function _tryAgain($search, $form, $errors=array()) { diff --git a/include/class.search.php b/include/class.search.php index 93322cc7248b08eabe7b801c01d76383bdfd5757..1597b063f4fd8cf13b19ebdfcedacfd5b67907cd 100644 --- a/include/class.search.php +++ b/include/class.search.php @@ -729,6 +729,20 @@ class SavedSearch extends VerySimpleModel { return $this->criteria ?: array(); } + function describeCriteria($criteria=false){ + $all = $this->getSupportedMatches($this->getRoot()); + $items = array(); + $criteria = $criteria ?: $this->getCriteria(); + foreach ($criteria as $C) { + list($path, $method, $value) = $C; + if (!isset($all[$path])) + continue; + list($label, $field) = $all[$path]; + $items[] = $field->describeSearch($method, $value, $label); + } + return implode(', ', $items); + } + /** * Fetch an AdvancedSearchForm instance for use in displaying or * configuring this search in the user interface. diff --git a/include/staff/queues-ticket.inc.php b/include/staff/queues-ticket.inc.php index 646a3c100d04a59c3c2f74c8cb391c0d939a58f1..acf872529df8b38f079667347504452feee46e09 100644 --- a/include/staff/queues-ticket.inc.php +++ b/include/staff/queues-ticket.inc.php @@ -61,7 +61,8 @@ $emitLevel = function($queues, $level=0) use ($all_queues, &$emitLevel) { </td> <td width="63%" colspan="<?php echo max(1, 5-$level); ?>"><a href="queues.php?id=<?php echo $q->getId(); ?>"><?php - echo Format::htmlchars($q->getFullName()); ?></a></td> + echo Format::htmlchars($q->getFullName()); ?></a> + <i class="faded-more pull-right icon-sort"></i></td> <td><?php echo Format::htmlchars($q->staff ? $q->staff->getName() : __('SYSTEM')); ?></td> <td><?php echo Format::htmlchars($q->getStatus()); ?></td> diff --git a/include/staff/templates/queue-savedsearches-nav.tmpl.php b/include/staff/templates/queue-savedsearches-nav.tmpl.php index d4f5d2f1fafa69dbb8c3e6f063f9241ac42da7f5..1ff6709ee692745e8e994753d0afcf4c0e7774f0 100644 --- a/include/staff/templates/queue-savedsearches-nav.tmpl.php +++ b/include/staff/templates/queue-savedsearches-nav.tmpl.php @@ -11,16 +11,6 @@ <div class="customQ-dropdown"> <ul class="scroll-height"> <!-- Start Dropdown and child queues --> - <?php foreach ($searches->findAll(array( - 'parent_id' => 0, - 'flags__hasbit' => SavedSearch::FLAG_PUBLIC, - )) as $q) { - include 'queue-subnavigation.tmpl.php'; - } ?> - <!-- Dropdown Titles --> - <li> - <h4><?php echo __('Personal Queues'); ?></h4> - </li> <?php foreach ($searches->findAll(array( 'staff_id' => $thisstaff->getId(), 'parent_id' => 0, @@ -30,6 +20,17 @@ )) as $q) { include 'queue-subnavigation.tmpl.php'; } ?> + <li> + <h4><?php echo __('Recent Searches'); ?></h4> + <?php foreach ($_SESSION['advsearch'] as $token=>$criteria) { + $q = new SavedSearch(array('root' => 'T')); + $q->id = 'adhoc,'.$token; + $q->title = $q->describeCriteria($criteria); + + include 'queue-subnavigation.tmpl.php'; + } ?> + <!-- Dropdown Titles --> + </li> </ul> <!-- Add Queue button sticky at the bottom --> <div class="add-queue"> diff --git a/include/staff/templates/queue-subnavigation.tmpl.php b/include/staff/templates/queue-subnavigation.tmpl.php index 29962c02e0878e0ff5d3c4b9cef4b2a83a2f6b74..e1f45d25b5cb29cd8ff4ec2184746c8da5edc13f 100644 --- a/include/staff/templates/queue-subnavigation.tmpl.php +++ b/include/staff/templates/queue-subnavigation.tmpl.php @@ -13,7 +13,7 @@ global $thisstaff; if ($hasChildren) { ?> <i class="icon-caret-down"></i> <?php } - if ($thisstaff->isAdmin()) { ?> + if ($thisstaff->isAdmin() || $q->isPrivate()) { ?> <!-- Edit Queue --> <div class="editQ pull-right"> <i class="icon-cog"></i> @@ -28,7 +28,8 @@ global $thisstaff; <li> <a href="<?php echo $queue->isPrivate() - ? sprintf('#" data-dialog="ajax.php/tickets/search/%d', $queue->getId()) + ? sprintf('#" data-dialog="ajax.php/tickets/search/%s', + urlencode($queue->getId())) : sprintf('queues.php?id=%d', $queue->getId()); ?>"> <i class="icon-fixed-width icon-pencil"></i> <?php echo __('Edit'); ?></a> @@ -44,7 +45,8 @@ global $thisstaff; <span class="pull-right">(?)</span> <!-- End Edit Queue --> <a class="truncate <?php if ($selected) echo ' active'; ?>" href="<?php echo $queue->getHref(); - ?>"><?php echo $q->getName(); ?></a> + ?>" title="<?php echo Format::htmlchars($q->getName()); ?>"><?php + echo Format::htmlchars($q->getName()); ?></a> <?php if ($hasChildren) { echo '<ul>'; foreach ($children as $q) { diff --git a/scp/ajax.php b/scp/ajax.php index 5bf9f155df950debcaa6e05709ca15393693b840..1069c3b078044a2bd3acffa8b57e626cc993cde5 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -170,6 +170,7 @@ $dispatcher = patterns('', url_get('^$', 'getAdvancedSearchDialog'), url_post('^$', 'doSearch'), url_get('^/(?P<id>\d+)$', 'editSearch'), + url_get('^/adhoc,(?P<key>[\w=/+]+)$', 'getAdvancedSearchDialog'), url_post('^/(?P<id>\d+)$', 'saveSearch'), url_delete('^/(?P<id>\d+)$', 'deleteSearch'), url_post('^/create$', 'createSearch'), diff --git a/scp/tickets.php b/scp/tickets.php index 297e285e23e3da3fc1b66e51b936f2953195a813..bb4eabedb3324ff290c665f4f2f508e14e6cbcf6 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -62,6 +62,25 @@ $queue_id = @$_REQUEST['queue'] ?: $cfg->getDefaultTicketQueueId(); if ((int) $queue_id) { $queue = CustomQueue::lookup($queue_id); } +elseif (isset($_SESSION['advsearch']) + && strpos($queue_id, 'adhoc') === 0 +) { + list(,$key) = explode(',', $queue_id, 2); + // XXX: De-duplicate and simplify this code + $queue = SavedSearch::create(array( + 'title' => __("Advanced Search"), + 'root' => 'T', + )); + // For queue=queue, use the most recent search + if (!$key) { + reset($_SESSION['advsearch']); + $key = key($_SESSION['advsearch']); + } + $queue->config = $_SESSION['advsearch'][$key]; + // Slight hack here to make the `adhoc` queue be selected + $_REQUEST['queue'] = 'adhoc,'.$key; +} + // Configure form for file uploads $response_form = new SimpleForm(array( @@ -391,17 +410,6 @@ as $q) { }); } -if (isset($_SESSION['advsearch'])) { - // XXX: De-duplicate and simplify this code - $adhoc = SavedSearch::create(array( - 'title' => __("Advanced Search"), - 'root' => 'T', - )); - $adhoc->config = $_SESSION['advsearch']; - if ($_REQUEST['queue'] == 'adhoc') - $queue = $adhoc; -} - // Add my advanced searches $nav->addSubMenu(function() use ($queue, $adhoc) { global $thisstaff;