Newer
Older
<?php
/*********************************************************************
ajax.search.php
AJAX interface for searches, queue management, etc.
Jared Hancock <jared@osticket.com>
Peter Rotich <peter@osticket.com>
Copyright (c) 2006-2014 osTicket
http://www.osticket.com
Released under the GNU General Public License WITHOUT ANY WARRANTY.
See LICENSE.TXT for details.
vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
if(!defined('INCLUDE_DIR')) die('403');
include_once(INCLUDE_DIR.'class.ticket.php');
require_once(INCLUDE_DIR.'class.ajax.php');
class SearchAjaxAPI extends AjaxController {
function getAdvancedSearchDialog($key=false, $context='advsearch') {
global $thisstaff;
if (!$thisstaff)
Http::response(403, 'Agent login required');
'parent_id' => @$_GET['parent_id'] ?: 0,
if ($search->parent_id) {
$search->flags |= SavedSearch::FLAG_INHERIT_COLUMNS;
}
if (isset($_SESSION[$context]) && $key && $_SESSION[$context][$key])
$search->config = $_SESSION[$context][$key];
$this->_tryAgain($search, $search->getForm());
}
function editSearch($id) {
global $thisstaff;
$search = SavedSearch::lookup($id);
if (!$thisstaff)
Http::response(403, 'Agent login is required');
elseif (!$search || !$search->checkAccess($thisstaff))
Http::response(404, 'No such saved search');
$this->_tryAgain($search, $search->getForm());
}
function addField($name) {
global $thisstaff;
if (!$thisstaff)
Http::response(403, 'Agent login required');
$search = new SavedSearch(array('root'=>'T'));
$searchable = $search->getSupportedMatches();
if (!($F = $searchable[$name]))
Http::response(404, 'No such field: ', print_r($name, true));
$fields = SavedSearch::getSearchField($F, $name);
$form = new AdvancedSearchForm($fields);
// Check the box to search the field by default
if ($F = $form->getField("{$name}+search"))
$F->value = true;
ob_start();
include STAFFINC_DIR . 'templates/advanced-search-field.tmpl.php';
$html = ob_get_clean();
return $this->encode(array(
'success' => true,
'html' => $html,
));
}
function doSearch() {
$search = new SavedSearch(array('root' => 'T'));
$form = $search->getForm($_POST);
if (false === $this->_setupSearch($search, $form)) {
return;
}
Http::response(200, $this->encode(array(
'redirect' => 'tickets.php?queue=adhoc',
function _hasErrors(SavedSearch $search, $form) {
if (!$form->isValid()) {
$this->_tryAgain($search, $form);
return true;
}
}
function _setupSearch(SavedSearch $search, $form, $key='advsearch') {
if ($this->_hasErrors($search, $form))
return false;
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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(), $info=array()) {
$matches = $search->getSupportedMatches();
include STAFFINC_DIR . 'templates/advanced-search.tmpl.php';
}
global $thisstaff;
Http::response(403, 'Agent login is required');
if ($id) { // update
$search = SavedSearch::lookup($id);
} else { // new search
$search = SavedSearch::create(array('root' => 'T'));
$search->staff_id = $thisstaff->getId();
}
if (!$search || !$search->checkAccess($thisstaff))
Http::response(404, 'No such saved search');
if (false === $this->_saveSearch($search))
return;
$info = array(
'msg' => sprintf('%s %s %s',
__('Search'),
$id ? __('updated') : __('created'),
__('successfully')),
);
$this->_tryAgain($search, $search->getForm(), null, $info);
function _saveSearch(SavedSearch $search) {
$form = $search->getForm($_POST);
$errors = array();
if (!$search->update($_POST, $errors)
$this->_tryAgain($search, $form, $errors);
return false;
if (false === $this->_setupSearch($search, $form)) {
return false;
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
elseif (!($column = QueueColumn::lookup($column_id))) {
Http::response(404, 'No such queue');
}
if ($_POST) {
$data_form = $column->getDataConfigForm($_POST);
if ($data_form->isValid()) {
$column->update($_POST, 'Ticket');
if ($column->save())
Http::response(201, 'Successfully updated');
}
}
$root = 'Ticket';
include STAFFINC_DIR . 'templates/queue-column-edit.tmpl.php';
function editSort($sort_id) {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
elseif (!($sort = QueueSort::lookup($sort_id))) {
Http::response(404, 'No such queue sort');
}
if ($_POST) {
$data_form = $sort->getDataConfigForm($_POST);
if ($data_form->isValid()) {
$sort->update($data_form->getClean() + $_POST);
if ($sort->save())
Http::response(201, 'Successfully updated');
}
}
include STAFFINC_DIR . 'templates/queue-sorting-edit.tmpl.php';
}
function getQueue($id) {
global $thisstaff;
$queue = SavedSearch::lookup($id);
if (!$thisstaff)
Http::response(403, 'Agent login is required');
elseif (!$queue || !$queue->checkAccess($thisstaff))
Http::response(404, 'No such queue');
Http::response(200, $this->encode(array(
'name' => $queue->getName(),
'criteria' => nl2br(Format::htmlchars($queue->describeCriteria())),
)));
}
function deleteQueue($id) {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
if ($id && (!($queue = CustomQueue::lookup($id)))) {
Http::response(404, 'No such queue');
}
if (!$queue || !$queue->checkAccess($thisstaff)) {
Http::response(404, 'No such queue');
}
if ($_POST) {
if (!$queue->delete()) {
Http::response(500, 'Unable to delete queue');
}
Http::response(201, 'Have a nice day');
$_SESSION['::sysmsgs']['msg'] = sprintf(__( 'Successfully deleted%s.'),
$queue->getName());
$info = array(
':action' => sprintf('#queue/%s/delete', $queue->getId()),
':title' => sprintf('%s %s', __('Please Confirm'), __('Queue Deletion')),
'warn' => __('Deleted Queues cannot be recovered'),
':message' => sprintf('Are you sure you want to delete %s queue?', $queue->getName()),
':confirm' => 'Yes, Delete!'
);
include STAFFINC_DIR . 'templates/confirm.tmpl.php';
function previewQueue($id=false) {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
if ($id && (!($queue = CustomQueue::lookup($id)))) {
Http::response(404, 'No such queue');
}
if (!$queue) {
$queue = CustomQueue::create();
}
$tickets = $queue->getQuery($form);
$count = 10; // count($queue->getBasicQuery($form));
include STAFFINC_DIR . 'templates/queue-preview.tmpl.php';
}
function addCondition() {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
elseif (!isset($_GET['field']) || !isset($_GET['id'])
|| !isset($_GET['object_id'])
) {
Http::response(400, '`field`, `id`, and `object_id` parameters required');
}
elseif (!is_numeric($_GET['object_id'])) {
Http::response(400, '`object_id` should be an integer');
}
$fields = SavedSearch::getSearchableFields('Ticket');
if (!isset($fields[$_GET['field']])) {
Http::response(400, sprintf('%s: No such searchable field'),
Format::htmlchars($_GET['field']));
}
list($label, $field) = $fields[$_GET['field']];
// Ensure `name` is preserved
$field_name = $_GET['field'];
$id = $_GET['id'];
$object_id = $_GET['object_id'];
$condition = new QueueColumnCondition();
include STAFFINC_DIR . 'templates/queue-column-condition.tmpl.php';
}
function addConditionProperty() {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
elseif (!isset($_GET['prop']) || !isset($_GET['condition'])) {
Http::response(400, '`prop` and `condition` parameters required');
}
$prop = $_GET['prop'];
include STAFFINC_DIR . 'templates/queue-column-condition-prop.tmpl.php';
}
function collectQueueCounts($ids=null) {
global $thisstaff;
if (!$thisstaff) {
Http::response(403, 'Agent login is required');
}
$queues = CustomQueue::objects()
->filter(Q::any(array(
'flags__hasbit' => CustomQueue::FLAG_PUBLIC,
'staff_id' => $thisstaff->getId(),
)));
if ($ids && is_array($ids))
$queues->filter(array('id__in' => $ids));
$query = Ticket::objects();
// Visibility contraints ------------------
// TODO: Consider SavedSearch::ignoreVisibilityConstraints()
foreach ($queues as $queue) {
$Q = $queue->getBasicQuery();
if (count($Q->extra) || $Q->isWindowed()) {
// XXX: This doesn't work
$query->annotate(array(
'q'.$queue->id => $Q->values_flat()
->aggregate(array('count' => SqlAggregate::COUNT('ticket_id')))
));
}
else {
$expr = SqlCase::N()->when(new SqlExpr(new Q($Q->constraints)), new SqlField('ticket_id'));
'q'.$queue->id => SqlAggregate::COUNT($expr, true)
}
Http::response(200, false, 'application/json');
return $this->encode($query->values()->one());
}