Skip to content
Snippets Groups Projects
Commit b63a33bb authored by Peter Rotich's avatar Peter Rotich
Browse files

Merge pull request #2 from greezybacon/feature/dynamic-forms


Dynamic data for osTicket

Sorta Reviewed-By: default avatarPeter Rotich <peter@osticket.com>
parents 3e3544cb 37623467
No related branches found
No related tags found
No related merge requests found
Showing
with 3177 additions and 129 deletions
......@@ -34,6 +34,9 @@ $dispatcher = patterns('',
url_post('^(?P<id>\d+)/attach$', 'uploadInlineImageClient'),
url_get('^(?P<namespace>[\w.]+)$', 'getDraftClient'),
url_post('^(?P<namespace>[\w.]+)$', 'createDraftClient')
)),
url('^/form/', patterns('ajax.forms.php:DynamicFormsAjaxAPI',
url_get('^help-topic/(?P<id>\d+)$', 'getClientFormsForHelpTopic')
))
);
print $dispatcher->resolve($ost->get_path_info());
......
......@@ -532,9 +532,11 @@ body {
width: 140px;
float: left;
}
label.required {
font-weight: bold;
}
#ticketForm div label.required,
#clientLogin div label.required {
font-weight: bold;
text-align: left;
}
#ticketForm div input,
......
......@@ -65,6 +65,8 @@ class Bootstrap {
define('FILE_CHUNK_TABLE',$prefix.'file_chunk');
define('ATTACHMENT_TABLE',$prefix.'attachment');
define('USER_TABLE',$prefix.'user');
define('USER_EMAIL_TABLE',$prefix.'user_email');
define('STAFF_TABLE',$prefix.'staff');
define('TEAM_TABLE',$prefix.'team');
......@@ -87,6 +89,15 @@ class Bootstrap {
define('TICKET_PRIORITY_TABLE',$prefix.'ticket_priority');
define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
define('FORM_SEC_TABLE',$prefix.'form');
define('FORM_FIELD_TABLE',$prefix.'form_field');
define('LIST_TABLE',$prefix.'list');
define('LIST_ITEM_TABLE',$prefix.'list_items');
define('FORM_ENTRY_TABLE',$prefix.'form_entry');
define('FORM_ANSWER_TABLE',$prefix.'form_entry_values');
define('TOPIC_TABLE',$prefix.'help_topic');
define('SLA_TABLE', $prefix.'sla');
......@@ -153,6 +164,27 @@ class Bootstrap {
self::croak($ferror);
}
function loadCode() {
#include required files
require(INCLUDE_DIR.'class.ostsession.php');
require(INCLUDE_DIR.'class.usersession.php');
require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
require(INCLUDE_DIR.'class.log.php');
require(INCLUDE_DIR.'class.crypto.php');
require(INCLUDE_DIR.'class.timezone.php');
require(INCLUDE_DIR.'class.http.php');
require(INCLUDE_DIR.'class.signal.php');
require(INCLUDE_DIR.'class.nav.php');
require(INCLUDE_DIR.'class.page.php');
require_once(INCLUDE_DIR.'class.format.php'); //format helpers
require_once(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
require(INCLUDE_DIR.'class.mailer.php');
if (extension_loaded('mysqli'))
require_once INCLUDE_DIR.'mysqli.php';
else
require(INCLUDE_DIR.'mysql.php');
}
function croak($message) {
$msg = $message."\n\n".THISPAGE;
Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg,
......@@ -174,7 +206,7 @@ define('I18N_DIR', INCLUDE_DIR.'i18n/');
/*############## Do NOT monkey with anything else beyond this point UNLESS you really know what you are doing ##############*/
#Current version && schema signature (Changes from version to version)
define('THIS_VERSION','1.8.0-devel'); //Shown on admin panel
define('THIS_VERSION','1.8-git'); //Shown on admin panel
//Path separator
if(!defined('PATH_SEPARATOR')){
if(strpos($_ENV['OS'],'Win')!==false || !strcasecmp(substr(PHP_OS, 0, 3),'WIN'))
......@@ -187,6 +219,7 @@ if(!defined('PATH_SEPARATOR')){
ini_set('include_path', './'.PATH_SEPARATOR.INCLUDE_DIR.PATH_SEPARATOR.PEAR_DIR);
require(INCLUDE_DIR.'class.osticket.php');
require(INCLUDE_DIR.'class.misc.php');
// Determine the path in the URI used as the base of the osTicket
// installation
......@@ -195,26 +228,6 @@ if (!defined('ROOT_PATH') && ($rp = osTicket::get_root_path(dirname(__file__))))
Bootstrap::init();
#include required files
require(INCLUDE_DIR.'class.ostsession.php');
require(INCLUDE_DIR.'class.usersession.php');
require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
require(INCLUDE_DIR.'class.log.php');
require(INCLUDE_DIR.'class.crypto.php');
require(INCLUDE_DIR.'class.misc.php');
require(INCLUDE_DIR.'class.timezone.php');
require(INCLUDE_DIR.'class.http.php');
require(INCLUDE_DIR.'class.signal.php');
require(INCLUDE_DIR.'class.nav.php');
require(INCLUDE_DIR.'class.page.php');
require(INCLUDE_DIR.'class.format.php'); //format helpers
require(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
require(INCLUDE_DIR.'class.mailer.php');
if (extension_loaded('mysqli'))
require_once INCLUDE_DIR.'mysqli.php';
else
require(INCLUDE_DIR.'mysql.php');
#CURRENT EXECUTING SCRIPT.
define('THISPAGE', Misc::currentURL());
define('THISURI', $_SERVER['REQUEST_URI']);
......
......@@ -43,3 +43,10 @@
display: block;
opacity: 0.3;
}
div.section-break {
margin-top: 1em;
margin-bottom: 0.5em;
padding-top: 0.8em !important;
border-top: 1px solid #ccc;
}
......@@ -35,7 +35,7 @@ class ConfigAjaxAPI extends AjaxController {
global $cfg;
$config=array(
'allow_attachments' => (bool) $cfg->allowOnlineAttachments,
'allow_attachments' => (bool) $cfg->allowOnlineAttachments(),
'file_types' => $cfg->getAllowedFileTypes(),
'max_file_size' => (int) $cfg->getMaxFileSize(),
'max_file_uploads'=> (int) $cfg->getClientMaxFileUploads(),
......
......@@ -49,7 +49,8 @@ class ContentAjaxAPI extends AjaxController {
<tr><td width="130">%{ticket.id}</td><td>Ticket ID (internal ID)</td></tr>
<tr><td>%{ticket.number}</td><td>Ticket number (external ID)</td></tr>
<tr><td>%{ticket.email}</td><td>Email address</td></tr>
<tr><td>%{ticket.name}</td><td>Full name</td></tr>
<tr><td>%{ticket.name}</td><td>Full name &mdash;
<em>see name expansion</em></td></tr>
<tr><td>%{ticket.subject}</td><td>Subject</td></tr>
<tr><td>%{ticket.phone}</td><td>Phone number | ext</td></tr>
<tr><td>%{ticket.status}</td><td>Status</td></tr>
......@@ -80,6 +81,18 @@ class ContentAjaxAPI extends AjaxController {
<tr><td>%{reset_link}</td>
<td>Reset link used by the password reset feature</td></tr>
</table>
<table width="100%" border="0" cellspacing=1 cellpadding=1>
<tr><td colspan="2"><b>Name Expansion</b></td></tr>
<tr><td>.first</td><td>First Name</td></tr>
<tr><td>.middle</td><td>Middle Name(s)</td></tr>
<tr><td>.last</td><td>Last Name</td></tr>
<tr><td>.full</td><td>First Last</td></tr>
<tr><td>.legal</td><td>First M. Last</td></tr>
<tr><td>.short</td><td>First L.</td></tr>
<tr><td>.formal</td><td>Mr. Last</td></tr>
<tr><td>.shortformal</td><td>F. Last</td></tr>
<tr><td>.lastfirst</td><td>Last, First</td></tr>
</table>
</td>
</tr>
</table>
......
<?php
require_once(INCLUDE_DIR . 'class.topic.php');
require_once(INCLUDE_DIR . 'class.dynamic_forms.php');
class DynamicFormsAjaxAPI extends AjaxController {
function getForm($form_id) {
$form = DynamicForm::lookup($form_id);
if (!$form) return;
foreach ($form->getFields() as $field) {
$field->render();
}
}
function getFormsForHelpTopic($topic_id, $client=false) {
$topic = Topic::lookup($topic_id);
if ($topic->ht['form_id']
&& ($form = DynamicForm::lookup($topic->ht['form_id'])))
$form->render(!$client);
}
function getClientFormsForHelpTopic($topic_id) {
return $this->getFormsForHelpTopic($topic_id, true);
}
function getFieldConfiguration($field_id) {
$field = DynamicFormField::lookup($field_id);
include(STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php');
}
function saveFieldConfiguration($field_id) {
$field = DynamicFormField::lookup($field_id);
if (!$field->setConfiguration())
include(STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php');
else
$field->save();
}
function getUserInfo($user_id) {
$user = User::lookup($user_id);
$data = $user->ht;
$data['email'] = $user->default_email->address;
$custom = array();
foreach ($user->getDynamicData() as $cd) {
$cd->addMissingFields();
foreach ($cd->getFields() as $f) {
if ($f->get('name') == 'name')
$f->value = $user->getFullName();
elseif ($f->get('name') == 'email')
$f->value = $user->getEmail();
}
$custom[] = $cd->getForm();
}
include(STAFFINC_DIR . 'templates/user-info.tmpl.php');
}
function saveUserInfo($user_id) {
$user = User::lookup($user_id);
$custom_data = $user->getDynamicData();
$custom = array();
$valid = true;
foreach ($custom_data as $cd) {
$cd->addMissingFields();
$cf = $custom[] = $cd->getForm();
$valid &= $cd->isValid();
}
if (!$valid) {
include(STAFFINC_DIR . 'templates/user-info.tmpl.php');
return;
}
// Save custom data
foreach ($custom_data as $cd) {
foreach ($cd->getFields() as $f) {
if ($f->get('name') == 'name') {
$user->name = $f->getClean();
$user->save();
}
elseif ($f->get('name') == 'email') {
$user->default_email->address = $f->getClean();
$user->default_email->save();
}
}
$cd->save();
}
}
}
?>
......@@ -17,6 +17,7 @@
if(!defined('INCLUDE_DIR')) die('403');
include_once(INCLUDE_DIR.'class.ticket.php');
require_once(INCLUDE_DIR.'class.ajax.php');
class TicketsAjaxAPI extends AjaxController {
......@@ -30,8 +31,10 @@ class TicketsAjaxAPI extends AjaxController {
$limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
$tickets=array();
$sql='SELECT DISTINCT ticketID, email'
.' FROM '.TICKET_TABLE
$sql='SELECT DISTINCT ticketID, email.address AS email'
.' FROM '.TICKET_TABLE.' ticket'
.' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
.' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
.' WHERE ticketID LIKE \''.db_input($_REQUEST['q'], false).'%\'';
$sql.=' AND ( staff_id='.db_input($thisstaff->getId());
......@@ -43,12 +46,17 @@ class TicketsAjaxAPI extends AjaxController {
$sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
$sql.=' ) '
.' ORDER BY created LIMIT '.$limit;
.' ORDER BY ticket.created LIMIT '.$limit;
if(($res=db_query($sql)) && db_num_rows($res)) {
while(list($id, $email)=db_fetch_row($res))
$tickets[] = array('id'=>$id, 'email'=>$email, 'value'=>$id, 'info'=>"$id - $email");
while(list($id, $email)=db_fetch_row($res)) {
$info = "$id - $email";
$tickets[] = array('id'=>$id, 'email'=>$email, 'value'=>$id,
'info'=>$info, 'matches'=>$_REQUEST['q']);
}
}
if (!$tickets)
return self::lookupByEmail();
return $this->json_encode($tickets);
}
......@@ -60,9 +68,15 @@ class TicketsAjaxAPI extends AjaxController {
$limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
$tickets=array();
$sql='SELECT email, count(ticket_id) as tickets '
.' FROM '.TICKET_TABLE
.' WHERE email LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' ';
$sql='SELECT email.address AS email, count(ticket.ticket_id) as tickets '
.' FROM '.TICKET_TABLE.' ticket'
.' JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
.' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
.' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_id = user.id
AND entry.object_type=\'U\')
LEFT JOIN '.FORM_ANSWER_TABLE.' data ON (data.entry_id = entry.id)'
.' WHERE (email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\'
OR data.value LIKE \'%'.db_input($_REQUEST['q'], false).'%\')';
$sql.=' AND ( staff_id='.db_input($thisstaff->getId());
......@@ -73,22 +87,23 @@ class TicketsAjaxAPI extends AjaxController {
$sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
$sql.=' ) '
.' GROUP BY email '
.' ORDER BY created LIMIT '.$limit;
.' GROUP BY email.address '
.' ORDER BY ticket.created LIMIT '.$limit;
if(($res=db_query($sql)) && db_num_rows($res)) {
while(list($email, $count)=db_fetch_row($res))
$tickets[] = array('email'=>$email, 'value'=>$email, 'info'=>"$email ($count)");
$tickets[] = array('email'=>$email, 'value'=>$email,
'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']);
}
return $this->json_encode($tickets);
}
function search() {
function _search($req) {
global $thisstaff, $cfg;
$result=array();
$select = 'SELECT count( DISTINCT ticket.ticket_id) as tickets ';
$select = 'SELECT DISTINCT ticket.ticket_id';
$from = ' FROM '.TICKET_TABLE.' ticket ';
$where = ' WHERE 1 ';
......@@ -104,15 +119,15 @@ class TicketsAjaxAPI extends AjaxController {
$where.=' ) ';
//Department
if($_REQUEST['deptId'])
$where.=' AND ticket.dept_id='.db_input($_REQUEST['deptId']);
if($req['deptId'])
$where.=' AND ticket.dept_id='.db_input($req['deptId']);
//Help topic
if($_REQUEST['topicId'])
$where.=' AND ticket.topic_id='.db_input($_REQUEST['topicId']);
if($req['topicId'])
$where.=' AND ticket.topic_id='.db_input($req['topicId']);
//Status
switch(strtolower($_REQUEST['status'])) {
switch(strtolower($req['status'])) {
case 'open':
$where.=' AND ticket.status="open" ';
break;
......@@ -128,9 +143,9 @@ class TicketsAjaxAPI extends AjaxController {
}
//Assignee
if(isset($_REQUEST['assignee']) && strcasecmp($_REQUEST['status'], 'closed')) {
$id=preg_replace("/[^0-9]/", "", $_REQUEST['assignee']);
$assignee = $_REQUEST['assignee'];
if(isset($req['assignee']) && strcasecmp($req['status'], 'closed')) {
$id=preg_replace("/[^0-9]/", "", $req['assignee']);
$assignee = $req['assignee'];
$where.= ' AND ( ( ticket.status="open" ';
if($assignee[0]=='t')
$where.=' AND ticket.team_id='.db_input($id);
......@@ -141,19 +156,19 @@ class TicketsAjaxAPI extends AjaxController {
$where.=')';
if($_REQUEST['staffId'] && !$_REQUEST['status']) //Assigned TO + Closed By
$where.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") ';
elseif(isset($_REQUEST['staffId'])) // closed by any
if($req['staffId'] && !$req['status']) //Assigned TO + Closed By
$where.= ' OR (ticket.staff_id='.db_input($req['staffId']). ' AND ticket.status="closed") ';
elseif(isset($req['staffId'])) // closed by any
$where.= ' OR ticket.status="closed" ';
$where.= ' ) ';
} elseif($_REQUEST['staffId']) {
$where.=' AND (ticket.staff_id='.db_input($_REQUEST['staffId']).' AND ticket.status="closed") ';
} elseif($req['staffId']) {
$where.=' AND (ticket.staff_id='.db_input($req['staffId']).' AND ticket.status="closed") ';
}
//dates
$startTime =($_REQUEST['startDate'] && (strlen($_REQUEST['startDate'])>=8))?strtotime($_REQUEST['startDate']):0;
$endTime =($_REQUEST['endDate'] && (strlen($_REQUEST['endDate'])>=8))?strtotime($_REQUEST['endDate']):0;
$startTime =($req['startDate'] && (strlen($req['startDate'])>=8))?strtotime($req['startDate']):0;
$endTime =($req['endDate'] && (strlen($req['endDate'])>=8))?strtotime($req['endDate']):0;
if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0))
$startTime=$endTime=0;
......@@ -164,23 +179,65 @@ class TicketsAjaxAPI extends AjaxController {
$where.=' AND ticket.created<=FROM_UNIXTIME('.$endTime.')';
//Query
if($_REQUEST['query']) {
$queryterm=db_real_escape($_REQUEST['query'], false);
$from.=' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON (ticket.ticket_id=thread.ticket_id )';
$where.=" AND ( ticket.email LIKE '%$queryterm%'"
." OR ticket.name LIKE '%$queryterm%'"
." OR ticket.subject LIKE '%$queryterm%'"
if($req['query']) {
$queryterm=db_real_escape($req['query'], false);
$from.=' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON (ticket.ticket_id=thread.ticket_id )'
.' LEFT JOIN '.FORM_ENTRY_TABLE.' tentry ON (tentry.object_id = ticket.ticket_id
AND tentry.object_type="T")
LEFT JOIN '.FORM_ANSWER_TABLE.' tans ON (tans.entry_id = tentry.id
AND tans.value_id IS NULL)
LEFT JOIN '.FORM_ENTRY_TABLE.' uentry ON (uentry.object_id = ticket.user_id
AND uentry.object_type="U")
LEFT JOIN '.FORM_ANSWER_TABLE.' uans ON (uans.entry_id = uentry.id
AND uans.value_id IS NULL)
LEFT JOIN '.USER_TABLE.' user ON (ticket.user_id = user.id)
LEFT JOIN '.USER_EMAIL_TABLE.' uemail ON (user.id = uemail.user_id)';
$where.=" AND ( uemail.address LIKE '%$queryterm%'"
." OR user.name LIKE '%$queryterm%'"
." OR tans.value LIKE '%$queryterm%'"
." OR uans.value LIKE '%$queryterm%'"
." OR thread.title LIKE '%$queryterm%'"
." OR thread.body LIKE '%$queryterm%'"
.' )';
}
// Dynamic fields
$dynfields='(SELECT entry.object_id, value, value_id FROM '.FORM_ANSWER_TABLE.' ans '.
'LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.id=ans.entry_id '.
'LEFT JOIN '.FORM_FIELD_TABLE.' field ON field.id=ans.field_id '.
'WHERE field.name = %1$s AND entry.object_type="T")';
foreach (TicketForm::getInstance()->getFields() as $f) {
if ($f->get('name') && isset($req[$f->getFormName()])
&& ($val = $req[$f->getFormName()])) {
$name = 'dyn_'.$f->get('id');
$from .= ' LEFT JOIN '.sprintf($dynfields, db_input($f->get('name')))
." $name ON ($name.object_id = ticket.ticket_id)";
$where .= " AND ($name.value_id = ".db_input($val)
. " OR $name.value LIKE '%".db_real_escape($val)."%')";
}
}
$sql="$select $from $where";
if(($tickets=db_result(db_query($sql)))) {
$result['success'] =sprintf("Search criteria matched %s - <a href='tickets.php?%s'>view</a>",
($tickets>1?"$tickets tickets":"$tickets ticket"),
str_replace(array('&amp;', '&'), array('&', '&amp;'), $_SERVER['QUERY_STRING']));
$res = db_query($sql);
while (list($tickets[]) = db_fetch_row($res));
$tickets = array_filter($tickets);
return $tickets;
}
function search() {
$tickets = self::_search($_REQUEST);
if (count($tickets)) {
$uid = md5($_SERVER['QUERY_STRING']);
$_SESSION["adv_$uid"] = $tickets;
$result['success'] =sprintf(
"Search criteria matched %d %s - <a href='tickets.php?%s'>view</a>",
count($tickets), (count($tickets)>1?"tickets":"ticket"),
'advsid='.$uid
);
} else {
$result['fail']='No tickets found matching your search criteria.';
}
......
......@@ -31,9 +31,10 @@ class UsersAjaxAPI extends AjaxController {
$limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
$users=array();
$sql='SELECT DISTINCT email, name '
.' FROM '.TICKET_TABLE
.' WHERE email LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '
$sql='SELECT DISTINCT email.address, name '
.' FROM '.USER_TABLE.' user '
.' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id '
.' WHERE email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '
.' ORDER BY created '
.' LIMIT '.$limit;
......
......@@ -8,15 +8,25 @@ class TicketApiController extends ApiController {
# Supported arguments -- anything else is an error. These items will be
# inspected _after_ the fixup() method of the ApiXxxDataParser classes
# so that all supported input formats should be supported
function getRequestStructure($format) {
function getRequestStructure($format, $data=null) {
$supported = array(
"alert", "autorespond", "source", "topicId",
"name", "email", "subject", "phone", "phone_ext",
"attachments" => array("*" =>
array("name", "type", "data", "encoding")
),
"message", "ip", "priorityId"
);
# Fetch dynamic form field names for the given help topic and add
# the names to the supported request structure
if (isset($data['topicId'])) {
$topic=Topic::lookup($data['topicId']);
$form=DynamicForm::lookup($topic->ht['form_id']);
foreach ($form->getDynamicFields() as $field)
$supported[] = $field->get('name');
}
$form = TicketForm::lookup()->instanciate();
foreach ($form->getDynamicFields() as $field)
$supported[] = $field->get('name');
if(!strcasecmp($format, 'email')) {
$supported = array_merge($supported, array('header', 'mid',
......@@ -90,6 +100,15 @@ class TicketApiController extends ApiController {
# Create the ticket with the data (attempt to anyway)
$errors = array();
if ($topic=Topic::lookup($data['topicId'])) {
if ($form=DynamicForm::lookup($topic->ht['form_id'])) {
$form = $form->instanciate();
if (!$form->isValid())
$errors += $form->errors();
}
}
$ticket = Ticket::create($data, $errors, $data['source'], $autorespond, $alert);
# Return errors (?)
if (count($errors)) {
......@@ -105,6 +124,12 @@ class TicketApiController extends ApiController {
return $this->exerr(500, "Unable to create new ticket: unknown error");
}
# Save dynamic form
if (isset($form)) {
$form->setTicketId($ticket->getId());
$form->save();
}
return $ticket;
}
......
......@@ -235,7 +235,7 @@ class ApiController {
* Structure to validate the request against -- must be overridden to be
* useful
*/
function getRequestStructure($format) { return array(); }
function getRequestStructure($format, $data=null) { return array(); }
/**
* Simple validation that makes sure the keys of a parsed request are
* expected. It is assumed that the functions actually implementing the
......@@ -266,7 +266,7 @@ class ApiController {
function validate(&$data, $format) {
return $this->validateRequestStructure(
$data,
$this->getRequestStructure($format)
$this->getRequestStructure($format, $data)
);
}
......
......@@ -24,6 +24,8 @@ class Client {
var $username;
var $email;
var $_answers;
var $ticket_id;
var $ticketID;
......@@ -40,11 +42,14 @@ class Client {
if(!$id && !($id=$this->getId()))
return false;
$sql='SELECT ticket_id, ticketID, name, email, phone, phone_ext '
.' FROM '.TICKET_TABLE
$sql='SELECT ticket.ticket_id, ticketID, email.address as email '
.' FROM '.TICKET_TABLE.' ticket '
.' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
.' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
.' WHERE ticketID='.db_input($id);
if($email)
$sql.=' AND email='.db_input($email);
$sql.=' AND email.address = '.db_input($email);
if(!($res=db_query($sql)) || !db_num_rows($res))
return NULL;
......@@ -53,15 +58,26 @@ class Client {
$this->id = $this->ht['ticketID']; //placeholder
$this->ticket_id = $this->ht['ticket_id'];
$this->ticketID = $this->ht['ticketID'];
$this->fullname = ucfirst($this->ht['name']);
$user = User::lookup(array('emails__address'=>$this->ht['email']));
$this->fullname = $user->getFullName();
$this->username = $this->ht['email'];
$this->email = $this->ht['email'];
$this->stats = array();
return($this->id);
}
function loadDynamicData() {
$this->_answers = array();
foreach (DynamicFormEntry::forClient($this->getId()) as $form)
foreach ($form->getAnswers() as $answer)
$this->_answers[$answer->getField()->get('name')] =
$answer->getValue();
}
function reload() {
return $this->load();
}
......@@ -87,13 +103,9 @@ class Client {
}
function getPhone() {
return $this->ht['phone'];
return $this->_answers['phone'];
}
function getPhoneExt() {
return $this->ht['phone_ext'];
}
function getTicketID() {
return $this->ticketID;
}
......@@ -120,9 +132,11 @@ class Client {
/* ------------- Static ---------------*/
function getLastTicketIdByEmail($email) {
$sql='SELECT ticketID FROM '.TICKET_TABLE
.' WHERE email='.db_input($email)
.' ORDER BY created '
$sql='SELECT ticket.ticketID '.TICKET_TABLE.' ticket '
.' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
.' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
.' WHERE email.address = '.db_input($email)
.' ORDER BY ticket.created '
.' LIMIT 1';
if(($res=db_query($sql)) && db_num_rows($res))
list($tid) = db_fetch_row($res);
......@@ -175,12 +189,12 @@ class Client {
//See if we can fetch local ticket id associated with the ID given
if(($ticket=Ticket::lookupByExtId($ticketID, $email)) && $ticket->getId()) {
//At this point we know the ticket ID is valid.
//TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets??
//TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets??
//Check the email given.
# Require auth token for automatic logins (GET METHOD).
if (!strcasecmp($ticket->getEmail(), $email) && (!$auto_login || $auth === $ticket->getAuthToken())) {
//valid match...create session goodies for the client.
$user = new ClientSession($email,$ticket->getExtId());
$_SESSION['_client'] = array(); //clear.
......@@ -193,7 +207,7 @@ class Client {
//Log login info...
$msg=sprintf('%s/%s logged in [%s]', $ticket->getEmail(), $ticket->getExtId(), $_SERVER['REMOTE_ADDR']);
$ost->logDebug('User login', $msg);
//Regenerate session ID.
$sid=session_id(); //Current session id.
session_regenerate_id(TRUE); //get new ID.
......@@ -202,7 +216,7 @@ class Client {
return $user;
}
}
}
//If we get to this point we know the login failed.
......
......@@ -146,6 +146,7 @@ class OsticketConfig extends Config {
'allow_email_attachments' => true,
'allow_online_attachments' => true,
'allow_online_attachments_onlogin' => false,
'name_format' => 'full', # First Last
);
function OsticketConfig($section=null) {
......@@ -326,6 +327,10 @@ class OsticketConfig extends Config {
return $this->get('autolock_minutes');
}
function getDefaultNameFormat() {
return $this->get('name_format');
}
function getDefaultDeptId() {
return $this->get('default_dept_id');
}
......@@ -519,11 +524,6 @@ class OsticketConfig extends Config {
return ($this->get('enable_mail_polling'));
}
function allowPriorityChange() {
return ($this->get('allow_priority_change'));
}
function useEmailPriority() {
return ($this->get('use_email_priority'));
}
......@@ -768,7 +768,6 @@ class OsticketConfig extends Config {
$f['helpdesk_url']=array('type'=>'string', 'required'=>1, 'error'=>'Helpdesk URl required');
$f['helpdesk_title']=array('type'=>'string', 'required'=>1, 'error'=>'Helpdesk title required');
$f['default_dept_id']=array('type'=>'int', 'required'=>1, 'error'=>'Default Dept. required');
$f['default_template_id']=array('type'=>'int', 'required'=>1, 'error'=>'You must select template.');
$f['staff_session_timeout']=array('type'=>'int', 'required'=>1, 'error'=>'Enter idle time in minutes');
$f['client_session_timeout']=array('type'=>'int', 'required'=>1, 'error'=>'Enter idle time in minutes');
//Date & Time Options
......@@ -789,10 +788,10 @@ class OsticketConfig extends Config {
'helpdesk_title'=>$vars['helpdesk_title'],
'helpdesk_url'=>$vars['helpdesk_url'],
'default_dept_id'=>$vars['default_dept_id'],
'default_template_id'=>$vars['default_template_id'],
'max_page_size'=>$vars['max_page_size'],
'log_level'=>$vars['log_level'],
'log_graceperiod'=>$vars['log_graceperiod'],
'name_format'=>$vars['name_format'],
'passwd_reset_period'=>$vars['passwd_reset_period'],
'staff_max_logins'=>$vars['staff_max_logins'],
'staff_login_timeout'=>$vars['staff_login_timeout'],
......@@ -861,7 +860,6 @@ class OsticketConfig extends Config {
'default_sla_id'=>$vars['default_sla_id'],
'max_open_tickets'=>$vars['max_open_tickets'],
'autolock_minutes'=>$vars['autolock_minutes'],
'allow_priority_change'=>isset($vars['allow_priority_change'])?1:0,
'use_email_priority'=>isset($vars['use_email_priority'])?1:0,
'enable_captcha'=>isset($vars['enable_captcha'])?1:0,
'log_ticket_activity'=>isset($vars['log_ticket_activity'])?1:0,
......@@ -889,6 +887,7 @@ class OsticketConfig extends Config {
function updateEmailsSettings($vars, &$errors) {
$f=array();
$f['default_template_id']=array('type'=>'int', 'required'=>1, 'error'=>'You must select template.');
$f['default_email_id']=array('type'=>'int', 'required'=>1, 'error'=>'Default email required');
$f['alert_email_id']=array('type'=>'int', 'required'=>1, 'error'=>'Selection required');
$f['admin_email']=array('type'=>'email', 'required'=>1, 'error'=>'System admin email required');
......@@ -903,6 +902,7 @@ class OsticketConfig extends Config {
return false;
return $this->updateAll(array(
'default_template_id'=>$vars['default_template_id'],
'default_email_id'=>$vars['default_email_id'],
'alert_email_id'=>$vars['alert_email_id'],
'default_smtp_id'=>$vars['default_smtp_id'],
......
This diff is collapsed.
......@@ -18,6 +18,17 @@ class Filter {
var $id;
var $ht;
static $match_types = array(
'Basic Fields' => array(
'name' => 'Name',
'email' => 'Email',
'subject' => 'Subject',
'body' => 'Body/Text',
'reply-to' => 'Reply-To Email',
'reply-to-name' => 'Reply-To Name',
),
);
function Filter($id) {
$this->id=0;
$this->load($id);
......@@ -165,7 +176,7 @@ class Filter {
function addRule($what, $how, $val,$extra=array()) {
$rule= array_merge($extra,array('w'=>$what, 'h'=>$how, 'v'=>$val));
$rule= array_merge($extra,array('what'=>$what, 'how'=>$how, 'val'=>$val));
$rule['filter_id']=$this->getId();
return FilterRule::create($rule,$errors); # nolint
......@@ -299,13 +310,28 @@ class Filter {
$ticket['cannedResponseId'] = $this->getCannedResponse();
}
/* static */ function getSupportedMatches() {
return array(
'name'=> 'Name',
'email'=> 'Email',
'subject'=> 'Subject',
'body'=> 'Body/Text'
);
foreach (static::$match_types as $k=>&$v) {
if (is_callable($v))
$v = $v();
}
unset($v);
return static::$match_types;
}
static function addSupportedMatches($group, $callable) {
static::$match_types[$group] = $callable;
}
static function getSupportedMatchFields() {
$keys = array();
foreach (static::getSupportedMatches() as $group=>$matches) {
foreach ($matches as $key=>$label) {
$keys[] = $key;
}
}
return $keys;
}
/* static */ function getSupportedMatchTypes() {
return array(
'equal'=> 'Equal',
......@@ -370,7 +396,7 @@ class Filter {
function save_rules($id,$vars,&$errors) {
$matches = array_keys(self::getSupportedMatches());
$matches = array_keys(self::getSupportedMatchFields());
$types = array_keys(self::getSupportedMatchTypes());
$rules=array();
......@@ -382,7 +408,9 @@ class Filter {
$errors["rule_$i"]='Invalid match type selection';
elseif(!$vars["rule_v$i"])
$errors["rule_$i"]='Value required';
elseif($vars["rule_w$i"]=='email' && $vars["rule_h$i"]=='equal' && !Validator::is_email($vars["rule_v$i"]))
elseif($vars["rule_w$i"]=='email'
&& $vars["rule_h$i"]=='equal'
&& !Validator::is_email($vars["rule_v$i"]))
$errors["rule_$i"]='Valid email required for the match type';
else //for everything-else...we assume it's valid.
$rules[]=array('what'=>$vars["rule_w$i"],
......@@ -640,22 +668,18 @@ class TicketFilter {
* deal with the data in the incoming ticket (based on $vars) will be considered.
* @see ::quickList() for more information.
*/
function TicketFilter($origin, $vars=null) {
function TicketFilter($origin, $vars=array()) {
//Normalize the target based on ticket's origin.
$this->target = self::origin2target($origin);
//Extract the vars we care about (fields we filter by!).
$this->vars = array_filter(array_map('trim',
array(
'email' => $vars['email'],
'subject' => $vars['subject'],
'name' => $vars['name'],
'body' => $vars['message'],
'emailId' => $vars['emailId'],
'reply-to' => @$vars['reply-to'],
'reply-to-name' => @$vars['reply-to-name'],
)));
$this->vars = array('body'=>$vars['message']);
$interest = Filter::getSupportedMatchFields();
foreach ($vars as $k=>$v) {
if (in_array($k, $interest))
$this->vars[$k] = trim($v);
}
//Init filters.
$this->build();
......
This diff is collapsed.
......@@ -41,17 +41,20 @@ class Internationalization {
* system language and reload the data.
*/
function loadDefaultData() {
# notrans -- do not translate the contents of this array
$models = array(
'email_template_group.yaml' => 'EmailTemplateGroup', # notrans
'department.yaml' => 'Dept', # notrans
'sla.yaml' => 'SLA', # notrans
// Note that department and sla are required for help_topic
'help_topic.yaml' => 'Topic', # notrans
'filter.yaml' => 'Filter', # notrans
'team.yaml' => 'Team', # notrans
'email_template_group.yaml' => 'EmailTemplateGroup',
'department.yaml' => 'Dept',
'sla.yaml' => 'SLA',
'form.yaml' => 'DynamicForm',
// Note that department, sla, and forms are required for
// help_topic
'help_topic.yaml' => 'Topic',
'filter.yaml' => 'Filter',
'team.yaml' => 'Team',
// Note that group requires department
'group.yaml' => 'Group', # notrans
'file.yaml' => 'AttachmentFile', # notrans
'group.yaml' => 'Group',
'file.yaml' => 'AttachmentFile',
);
$errors = array();
......
......@@ -22,10 +22,12 @@ include_once "JSON.php";
class JsonDataParser {
function parse($stream) {
$contents = '';
while (!feof($stream)) {
$contents .= fread($stream, 8192);
}
if (is_resource($stream)) {
$contents = '';
while (!feof($stream))
$contents .= fread($stream, 8192);
} else
$contents = $stream;
return self::decode($contents);
}
......
......@@ -207,7 +207,9 @@ class AdminNav extends StaffNav{
'title'=>'Ticket&nbsp;Filters','iconclass'=>'ticketFilters');
$subnav[]=array('desc'=>'SLA&nbsp;Plans','href'=>'slas.php','iconclass'=>'sla');
$subnav[]=array('desc'=>'API&nbsp;Keys','href'=>'apikeys.php','iconclass'=>'api');
$subnav[]=array('desc'=>'Site&nbsp;Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
$subnav[]=array('desc'=>'Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
$subnav[]=array('desc'=>'Forms','href'=>'forms.php','iconclass'=>'forms');
$subnav[]=array('desc'=>'Lists','href'=>'lists.php','iconclass'=>'lists');
break;
case 'emails':
$subnav[]=array('desc'=>'Emails','href'=>'emails.php', 'title'=>'Email Addresses', 'iconclass'=>'emailSettings');
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment