diff --git a/bootstrap.php b/bootstrap.php index 6132c2d1b842003c712630afe242029ecec80e28..55b747cb6cb142e1ccf94b71d25fa26f01f00e3e 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -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'); @@ -162,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(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'); + } + function croak($message) { $msg = $message."\n\n".THISPAGE; Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg, @@ -196,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 @@ -204,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']); diff --git a/include/ajax.forms.php b/include/ajax.forms.php index 37c8657c04cac53f6c83d98276d9e85842aca678..ac49c8cdb053f0b055f888cd2d74c1cfb5dabca5 100644 --- a/include/ajax.forms.php +++ b/include/ajax.forms.php @@ -39,6 +39,67 @@ class DynamicFormsAjaxAPI extends AjaxController { else $field->save(); } + + function _getUserForms() { + $static = new Form(array( + 'first' => new TextboxField(array( + 'label'=>'First Name', 'configuration'=>array('size'=>30)) + ), + 'last' => new TextboxField(array( + 'label'=>'Last Name', 'configuration'=>array('size'=>30)) + ), + 'email' => new TextboxField(array( + 'label'=>'Default Email', 'configuration'=>array( + 'validator'=>'email', 'size'=>40)) + ), + )); + + return $static; + } + + function getUserInfo($user_id) { + $user = User::lookup($user_id); + $static = $this->_getUserForms(); + + $data = $user->ht; + $data['email'] = $user->default_email->address; + $static->data($data); + + $custom = array(); + foreach ($user->getDynamicData() as $cd) + $custom[] = $cd->getForm(); + + include(STAFFINC_DIR . 'templates/user-info.tmpl.php'); + } + + function saveUserInfo($user_id) { + $user = User::lookup($user_id); + $static = $this->_getUserForms(); + $valid = $static->isValid(); + + $custom_data = $user->getDynamicData(); + $custom = array(); + foreach ($custom_data as $cd) { + $cf = $custom[] = $cd->getForm(); + $valid &= $cf->isValid(); + } + + if (!$valid) { + include(STAFFINC_DIR . 'templates/user-info.tmpl.php'); + return; + } + + $data = $static->getClean(); + $user->first = $data['first']; + $user->last = $data['last']; + $user->default_email->address = $data['email']; + $user->save(); + $user->default_email->save(); + + // Save custom data + foreach ($custom_data as $cd) + $cd->save(); + } } ?> diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index a981e5ae43605e459ddf5a03459216e8f061a9e0..771dcf7f6ba2270a1ab3db6183da77b957c68b84 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -30,13 +30,11 @@ class TicketsAjaxAPI extends AjaxController { $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25; $tickets=array(); - $sql='SELECT DISTINCT ticketID, email.value AS email' + $sql='SELECT DISTINCT ticketID, email.address AS email' .' FROM '.TICKET_TABLE.' ticket' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field ON email.field_id = field.id ' - .' WHERE field.name = "email"' - .' AND ticketID LIKE \''.db_input($_REQUEST['q'], false).'%\''; + .' 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()); @@ -64,13 +62,11 @@ class TicketsAjaxAPI extends AjaxController { $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25; $tickets=array(); - $sql='SELECT email.value AS email, count(ticket.ticket_id) as tickets ' + $sql='SELECT email.address AS email, count(ticket.ticket_id) as tickets ' .' FROM '.TICKET_TABLE.' ticket' - .' JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' JOIN '.FORM_FIELD_TABLE.' field ON email.field_id = field.id ' - .' WHERE field.name = "email"' - .' AND email.value LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '; + .' JOIN '.USER_TABLE.' user ON user.id = ticket.user_id' + .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id' + .' WHERE email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '; $sql.=' AND ( staff_id='.db_input($thisstaff->getId()); diff --git a/include/ajax.users.php b/include/ajax.users.php index d18f3c3323b889b3e155575b608f2e75fea61dd8..46e868827909bfdf68ebf39a3a5f79a065842fc4 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -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, concat_ws(" ", first, last) as 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; diff --git a/include/api.tickets.php b/include/api.tickets.php index a648d10f75d08447dceccd7f7e221cf2212599bd..b57f65125ec050cb0dff0f40f0c5d507476bd01c 100644 --- a/include/api.tickets.php +++ b/include/api.tickets.php @@ -126,7 +126,7 @@ class TicketApiController extends ApiController { # Save dynamic forms foreach ($forms as $f) { - $f->set('ticket_id', $ticket->getId()); + $f->setTicketId($ticket->getId()); $f->save(); } diff --git a/include/class.client.php b/include/class.client.php index 8cf29e31d031a0e327eec982c5b5dda64a9da21a..3c4ce5243e6d9dc2cb181724b12b6807ff20ee86 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -40,17 +40,19 @@ class Client { if(!$id && !($id=$this->getId())) return false; - $sql='SELECT ticket.ticket_id, ticketID, email.value as email, phone.value as phone ' + $sql='SELECT ticket.ticket_id, ticketID, email.address as email, phone.value as phone ' .' FROM '.TICKET_TABLE.' ticket ' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field1 ON email.field_id = field1.id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' phone ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field2 ON phone.field_id = field2.id ' - .' WHERE field1.name = "email" AND field2.name="phone" AND ticketID='.db_input($id); + .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id' + .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id' + .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON + (entry.object_id = ticket.ticket_id AND entry.object_type = "T")' + .' LEFT JOIN '.FORM_ANSWER_TABLE.' phone ON phone.entry_id = entry.id' + .' LEFT JOIN '.FORM_FIELD_TABLE.' field ON + (phone.field_id = field.id AND field.name="phone")' + .' WHERE ticketID='.db_input($id); if($email) - $sql.=' AND email.value = '.db_input($email); + $sql.=' AND email.address = '.db_input($email); if(!($res=db_query($sql)) || !db_num_rows($res)) return NULL; @@ -60,10 +62,8 @@ class Client { $this->ticket_id = $this->ht['ticket_id']; $this->ticketID = $this->ht['ticketID']; - $entry = DynamicFormEntry::forTicket($this->ticket_id); - foreach ($entry as $form) - if ($form->getAnswer('name')) - $this->fullname = $form->getAnswer('name'); + $user = User::lookup(array('emails__address'=>$this->ht['email'])); + $this->fullname = $user->getFullName(); $this->username = $this->ht['email']; $this->email = $this->ht['email']; @@ -132,10 +132,9 @@ class Client { /* ------------- Static ---------------*/ function getLastTicketIdByEmail($email) { $sql='SELECT ticket.ticketID '.TICKET_TABLE.' ticket ' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field ON email.field_id = field.id ' - .' WHERE field.name = "email" AND email.value = '.db_input($email) + .' 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)) diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 6aad0b264ea7d3f2f9ce99d14df668fae0249c83..0418bab1e1f3f966464d987d656476ed8f1c5c4d 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -31,6 +31,13 @@ class DynamicForm extends VerySimpleModel { 'pk' => array('id'), ); + // Registered form types + static $types = array( + 'T' => 'Ticket Information', + 'U' => 'User Information', + ); + + var $_form; var $_fields; var $_dfields; @@ -51,6 +58,12 @@ class DynamicForm extends VerySimpleModel { return $this->_dfields; } + // Multiple inheritance -- delegate to Form + function __call($what, $args) { + return call_user_func_array( + array($this->getForm(), $what), $args); + } + function hasField($name) { foreach ($this->getDynamicFields() as $f) if ($f->get('name') == $name) @@ -61,10 +74,11 @@ class DynamicForm extends VerySimpleModel { function getInstructions() { return $this->get('instructions'); } function getForm() { - $fields = $this->getFields(); - foreach ($fields as &$f) - $f = $f->getField(); - return new Form($fields, $this->title, $this->instructions); + if (!$this->_form) { + $fields = $this->getFields(); + $this->_form = new Form($fields, $this->title, $this->instructions); + } + return $this->_form; } function instanciate($sort=1) { @@ -72,6 +86,12 @@ class DynamicForm extends VerySimpleModel { 'form_id'=>$this->get('id'), 'sort'=>$sort)); } + function data($data) { + if ($data instanceof DynamicFormEntry) { + $this->_fields = $data->getFields(); + } + } + function save() { if (count($this->dirty)) $this->set('updated', new SqlFunction('NOW')); @@ -91,6 +111,42 @@ class DynamicForm extends VerySimpleModel { } return $inst; } + + static function addFormTypes($types) { + static::$types += $types; + } + + static function allTypes() { + return static::$types; + } +} + +class UserForm extends DynamicForm { + static function objects() { + $os = parent::objects(); + return $os->filter(array('type'=>'U')); + } + + function getStaticForm() { + static $form = null; + if (!$form) + $form = new Form(array( + 'email' => new TextboxField(array( + 'id'=>'email', 'label'=>'Email Address', 'required'=>true, + 'validator' => 'email', 'configuration'=>array( + 'autocomplete'=>false, 'classes'=>array('typeahead'), + 'size'=>40) + )), + 'name' => new TextboxField(array( + 'id'=>'name', 'label'=>'Full Name', 'required'=>true, + 'configuration' => array('size'=>40), + )), + 'phone' => new PhoneField(array( + 'id'=>'c', 'label'=>'Phone Number', 'required'=>false, 'default'=>'', + )), + ), 'User Information'); + return $form; + } } require_once(INCLUDE_DIR . "class.json.php"); @@ -236,8 +292,11 @@ class DynamicFormEntry extends VerySimpleModel { function getInstructions() { return $this->getForm()->getInstructions(); } function getForm() { - if (!$this->_form) + if (!$this->_form) { $this->_form = DynamicForm::lookup($this->get('form_id')); + if ($this->id) + $this->_form->data($this); + } return $this->_form; } @@ -274,9 +333,22 @@ class DynamicFormEntry extends VerySimpleModel { static $entries = array(); if (!isset($entries[$ticket_id])) $entries[$ticket_id] = DynamicFormEntry::objects() - ->filter(array('ticket_id'=>$ticket_id)); + ->filter(array('object_id'=>$ticket_id, 'object_type'=>'T')); return $entries[$ticket_id]; } + function setTicketId($ticket_id) { + $this->object_type = 'T'; + $this->object_id = $ticket_id; + } + + function forClient($user_id) { + return DynamicFormEntry::objects() + ->filter(array('object_id'=>$user_id, 'object_type'=>'U')); + } + function setClientId($user_id) { + $this->object_type = 'U'; + $this->object_id = $user_id; + } /** * addMissingFields diff --git a/include/class.forms.php b/include/class.forms.php index d0101784328340b7dd9e8ec06d110f9f57e08eec..cc5d07f07821a713fdb9370bc9954dd00662b883 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -23,14 +23,21 @@ class Form { var $title = 'Unnamed Form'; var $instructions = ''; + var $_errors; + function Form() { call_user_func_array(array($this, '__construct'), func_get_args()); } - function __construct($fields=array(), $title='Unnamed', $instructions='') { + function __construct($fields=array(), $title=false, $instructions=false) { $this->fields = $fields; $this->title = $title; $this->instructions = $instructions; } + function data($source) { + foreach ($this->fields as $name=>$f) + if (isset($source[$name])) + $f->value = $source[$name]; + } function getFields() { return $this->fields; @@ -39,16 +46,39 @@ class Form { function getInstructions() { return $this->instructions; } function isValid() { - $this->validate(); - foreach ($this->fields as $f) - if (!$f->isValidEntry()) - return false; - return true; + if (!is_array($this->_errors)) { + $this->_errors = array(); + $this->getClean(); + foreach ($this->getFields() as $field) + if ($field->errors()) + $this->_errors[$field->get('id')] = $field->errors(); + } + return !$this->_errors; + } + + function getClean() { + if (!$this->_clean) { + $this->_clean = array(); + foreach ($this->getFields() as $key=>$field) + $this->_clean[$key] = $field->getClean(); + } + return $this->_clean; + } + + function errors() { + return $this->_errors; } - function validate() { - foreach ($this->fields as $f) - $f->validateEntry(); + function render($staff=true, $title=false, $instructions=false) { + if ($title) + $this->title = $title; + if ($instructions) + $this->instructions = $instructions; + $form = $this; + if ($staff) + include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php'); + else + include(CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php'); } } @@ -159,7 +189,7 @@ class FormField { * useful error message indicating what is wrong with the input. */ function parse($value) { - return $value; + return trim($value); } /** @@ -233,7 +263,10 @@ class FormField { function getAnswer() { return $this->answer; } function getFormName() { - return '-field-id-'.$this->get('id'); + if (is_numeric($this->get('id'))) + return '-field-id-'.$this->get('id'); + else + return $this->get('id'); } function render() { @@ -512,10 +545,15 @@ class TextboxWidget extends Widget { $size = "size=\"{$config['size']}\""; if (isset($config['length'])) $maxlength = "maxlength=\"{$config['length']}\""; + if (isset($config['classes'])) + $classes = 'class="'.implode(' ', $config['classes']).'"'; + if (isset($config['autocomplete'])) + $autocomplete = 'autocomplete="'.($config['autocomplete']?'on':'off').'"'; ?> <span style="display:inline-block"> <input type="text" id="<?php echo $this->name; ?>" <?php echo $size . " " . $maxlength; ?> + <?php echo $classes.' '.$autocomplete; ?> name="<?php echo $this->name; ?>" value="<?php echo Format::htmlchars($this->value); ?>"/> </span> diff --git a/include/class.orm.php b/include/class.orm.php index 02e6baeaa1528ddda661d12654f4d4dbe39d9af5..86d3015f1525dff2dd90edea0448309901ac6fbf 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -29,6 +29,7 @@ class VerySimpleModel { function __construct($row) { $this->ht = $row; + $this->__setupForeignLists(); $this->dirty = array(); } @@ -38,10 +39,29 @@ class VerySimpleModel { function __get($field) { if (array_key_exists($field, $this->ht)) return $this->ht[$field]; - return $this->{$field}; + elseif (isset(static::$meta['joins'][$field])) { + // TODO: Support instrumented lists and such + $j = static::$meta['joins'][$field]; + $class = $j['fkey'][0]; + $v = $this->ht[$field] = $class::lookup($this->ht[$j['local']]); + return $v; + } } function set($field, $value) { + // Update of foreign-key by assignment to model instance + if (isset(static::$meta['joins'][$field])) { + $j = static::$meta['joins'][$field]; + // XXX: Ensure $value instanceof $j['fkey'][0] + if ($value->__new__) + $value->save(); + // Capture the object under the object's field name + $this->ht[$field] = $value; + // Capture the foreign key id value + $field = $j['local']; + $value = $value->{$j['fkey'][1]}; + // Fall through to the standard logic below + } // XXX: Fully support or die if updating pk // XXX: The contents of $this->dirty should be the value after the // previous fetch or save. For instance, if the value is changed more @@ -62,10 +82,45 @@ class VerySimpleModel { $this->set($field, $value); } - function _inspect() { + function __setupForeignLists() { + // Construct related lists + if (isset(static::$meta['joins'])) { + foreach (static::$meta['joins'] as $name => $j) { + if (isset($j['list']) && $j['list']) { + $fkey = $j['fkey']; + $this->{$name} = new InstrumentedList( + // Send Model, Foriegn-Field, Local-Id + array($fkey[0], $fkey[1], $this->{$j['local']}) + ); + } + } + } + } + + static function _inspect() { if (!static::$meta['table']) throw new OrmConfigurationError( - 'Model does not define meta.table', $this); + 'Model does not define meta.table', get_called_class()); + + // Break down foreign-key metadata + foreach (static::$meta['joins'] as $field => &$j) { + if (isset($j['reverse'])) { + list($model, $key) = explode('.', $j['reverse']); + $info = $model::$meta['joins'][$key]; + $constraint = array(); + foreach ($info['constraint'] as $foreign => $local) { + list(,$field) = explode('.', $local); + $constraint[$field] = "$model.$foreign"; + } + $j['constraint'] = $constraint; + $j['list'] = true; + } + // XXX: Make this better (ie. composite keys) + $keys = array_keys($j['constraint']); + $foreign = $j['constraint'][$keys[0]]; + $j['fkey'] = explode('.', $foreign); + $j['local'] = $keys[0]; + } } static function objects() { @@ -127,6 +182,8 @@ class VerySimpleModel { if (count($pk) == 1) $this->ht[$pk[0]] = db_insert_id(); $this->__new__ = false; + // Setup lists again + $this->__setupForeignLists(); } # Refetch row from database # XXX: Too much voodoo @@ -233,6 +290,12 @@ class QuerySet implements IteratorAggregate, ArrayAccess { return $this; } + function values_flat() { + $this->values = func_get_args(); + $this->iterator = 'FlatArrayIterator'; + return $this; + } + function all() { return $this->getIterator()->asArray(); } @@ -242,6 +305,10 @@ class QuerySet implements IteratorAggregate, ArrayAccess { return $compiler->compileCount($this); } + function exists() { + return $this->count() > 0; + } + // IteratorAggregate interface function getIterator() { if (!isset($this->_iterator)) @@ -267,7 +334,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess { return (string)$this->getQuery(); } - function getQuery() { + function getQuery($options=array()) { if (isset($this->query)) return $this->query; @@ -276,7 +343,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess { if (!$this->ordering && isset($model::$meta['ordering'])) $this->ordering = $model::$meta['ordering']; - $compiler = new $this->compiler(); + $compiler = new $this->compiler($options); $this->query = $compiler->compileSelect($this); return $this->query; @@ -290,9 +357,11 @@ class ModelInstanceIterator implements Iterator, ArrayAccess { var $position = 0; var $queryset; - function __construct($queryset) { - $this->model = $queryset->model; - $this->resource = $queryset->getQuery(); + function __construct($queryset=false) { + if ($queryset) { + $this->model = $queryset->model; + $this->resource = $queryset->getQuery(); + } } function buildModel($row) { @@ -353,7 +422,58 @@ class ModelInstanceIterator implements Iterator, ArrayAccess { } } +class FlatArrayIterator extends ModelInstanceIterator { + function __construct($queryset) { + $this->resource = $queryset->getQuery(); + } + function fillTo($index) { + while ($this->resource && $index >= count($this->cache)) { + if ($row = $this->resource->getRow()) { + $this->cache += $row; + } else { + $this->resource->close(); + $this->resource = null; + break; + } + } + } +} + +class InstrumentedList extends ModelInstanceIterator { + var $key; + var $id; + + function __construct($fkey, $queryset=false) { + list($model, $this->key, $this->id) = $fkey; + if (!$queryset) + $queryset = $model::objects()->filter(array($this->key=>$this->id)); + parent::__construct($queryset); + if (!$this->id) + $this->resource = null; + } + + function add($object) { + $object->{$this->key} = $this->id; + $object->save(); + $this->list[] = $object; + } + function remove($object) { + $object->delete(); + } + + function offsetUnset($a) { + $this->fillTo($a); + $this->cache[$a]->delete(); + } + function offsetSet($a, $b) { + $this->fillTo($a); + $this->cache[$a]->delete(); + $this->add($b); + } +} + class SqlCompiler { + var $options = array(); var $params = array(); var $joins = array(); var $aliases = array(); @@ -363,6 +483,11 @@ class SqlCompiler { 'exact' => '%$1s = %$2s' ); + function __construct($options=false) { + if ($options) + $this->options = array_merge($this->options, $options); + } + /** * Handles breaking down a field or model search descriptor into the * model search path, field, and operator parts. When used in a queryset @@ -508,7 +633,7 @@ class SqlCompiler { // Allow operators to be callable rather than sprintf // strings if (is_callable($op)) - $filter[] = $op($field, $value); + $filter[] = call_user_func($op, $field, $value); else $filter[] = sprintf($op, $field, $this->input($value)); } @@ -605,8 +730,8 @@ class MySqlCompiler extends SqlCompiler { } function input($what) { - if ($b instanceof QuerySet) { - $q = $b->getQuery(); + if ($what instanceof QuerySet) { + $q = $what->getQuery(array('nosort'=>true)); $this->params += $q->params; return '(' . (string)$q . ')'; } @@ -664,7 +789,7 @@ class MySqlCompiler extends SqlCompiler { } $sort = ''; - if ($queryset->ordering) { + if ($queryset->ordering && !isset($this->options['nosort'])) { $orders = array(); foreach ($queryset->ordering as $sort) { $dir = 'ASC'; @@ -753,13 +878,15 @@ class MysqlExecutor { $types = ''; $ps = array(); - foreach ($params as $p) { + foreach ($params as &$p) { if (is_int($p)) $types .= 'i'; elseif (is_string($p)) $types .= 's'; + // TODO: Emit error if param is null $ps[] = &$p; } + unset($p); array_unshift($ps, $types); call_user_func_array(array($this->stmt,'bind_param'), $ps); } @@ -804,6 +931,39 @@ class MysqlExecutor { return $output; } + function getRow() { + $output = array(); + $variables = array(); + + if (!isset($this->stmt)) + $this->_prepare(); + + foreach ($this->fields as $f) + $variables[] = &$output[]; // pass by reference + + call_user_func_array(array($this->stmt, 'bind_result'), $variables); + if (!$this->next()) + return false; + return $output; + } + + function getStruct() { + $output = array(); + $variables = array(); + + if (!isset($this->stmt)) + $this->_prepare(); + + foreach ($this->fields as $f) + $variables[] = &$output[$f->table][$f->name]; // pass by reference + + // TODO: Figure out what the table alias for the root model will be + call_user_func_array(array($this->stmt, 'bind_result'), $variables); + if (!$this->next()) + return false; + return $output; + } + function close() { if (!$this->stmt) return; diff --git a/include/class.ticket.php b/include/class.ticket.php index 2f22a11691851c30f5e49147d9632233cc6eb57f..12c30c02acad45938333a2e7de30ef0453cca320 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -31,6 +31,7 @@ include_once(INCLUDE_DIR.'class.priority.php'); include_once(INCLUDE_DIR.'class.sla.php'); include_once(INCLUDE_DIR.'class.canned.php'); require_once(INCLUDE_DIR.'class.dynamic_forms.php'); +require_once(INCLUDE_DIR.'class.user.php'); class Ticket { @@ -181,8 +182,31 @@ class Ticket { return $this->number; } + function getOwnerId() { + return $this->ht['user_id']; + } + + function getOwner() { + if (!isset($this->user)) + $this->user = User::lookup($this->getOwnerId()); + return $this->user; + } + function getEmail(){ - return $this->_answers['email']; + if ($o = $this->getOwner()) + return $o->getEmail(); + return null; + } + + function getReplyToEmail() { + if ($this->ht['user_email_id']) { + if (!isset($this->reply_email)) + $this->reply_email = UserEmail::lookup($this->ht['user_email_id']); + return $this->reply_email->address; + } + else { + return $this->getEmail(); + } } function getAuthToken() { @@ -191,7 +215,9 @@ class Ticket { } function getName(){ - return $this->_answers['name']; + if ($o = $this->getOwner()) + return $o->getFullName(); + return null; } function getSubject() { @@ -1704,13 +1730,12 @@ class Ticket { return 0; $sql ='SELECT ticket.ticket_id FROM '.TICKET_TABLE.' ticket ' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field ON email.field_id = field.id ' - .' WHERE field.name = "email" AND ticket.ticketID='.db_input($extId); + .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id' + .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id' + .' WHERE ticket.ticketID='.db_input($extId); if($email) - $sql .= ' AND email.value = '.db_input($email); + $sql .= ' AND email.address = '.db_input($email); if(($res=db_query($sql)) && db_num_rows($res)) list($id)=db_fetch_row($res); @@ -1817,6 +1842,8 @@ class Ticket { if(!$email || !Validator::is_email($email)) return null; + if (!$user = User::lookup(array('emails__address'=>$email))) + return null; $sql='SELECT count(open.ticket_id) as open, count(closed.ticket_id) as closed ' .' FROM '.TICKET_TABLE.' ticket ' @@ -1824,10 +1851,7 @@ class Ticket { ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\') ' .' LEFT JOIN '.TICKET_TABLE.' closed ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\')' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.ticket_id = ticket.ticket_id ' - .' LEFT JOIN '.FORM_ANSWER_TABLE.' email ON email.entry_id = entry.id ' - .' LEFT JOIN '.FORM_FIELD_TABLE.' field ON email.field_id = field.id ' - .' WHERE field.name = "email" AND email.value = '.db_input($email); + .' WHERE ticket.user_id = '.db_input($user->getId()); return db_fetch_array(db_query($sql)); } @@ -1841,7 +1865,7 @@ class Ticket { global $ost, $cfg, $thisclient, $_FILES; // Drop extra whitespace - foreach (array('email', 'phone', 'subject', 'name') as $f) + foreach (array('phone', 'subject') as $f) if (isset($vars[$f])) $vars[$f] = trim($vars[$f]); @@ -1924,6 +1948,13 @@ class Ticket { //Any error above is fatal. if($errors) return 0; + # Identify the user creating the ticket + $user_info = UserForm::getStaticForm()->getClean(); + if (isset($vars['emailId']) || !isset($user_info['email'])) + $user_info = $vars; + $user = User::fromForm($user_info); + $user_email = UserEmail::ensure($user_info['email']); + # Perform ticket filter actions on the new ticket arguments if ($ticket_filter) $ticket_filter->apply($vars); @@ -1972,6 +2003,8 @@ class Ticket { $extId=Ticket::genExtRandID(); $sql='INSERT INTO '.TICKET_TABLE.' SET created=NOW() ' .' ,lastmessage= NOW()' + .' ,user_id='.db_input($user->id) + .' ,user_email_id='.db_input($user_email->id) .' ,ticketID='.db_input($extId) .' ,dept_id='.db_input($deptId) .' ,topic_id='.db_input($topicId) diff --git a/include/class.user.php b/include/class.user.php new file mode 100644 index 0000000000000000000000000000000000000000..b6bc367f3392e0cf069e3c85fafb7a5d59f86781 --- /dev/null +++ b/include/class.user.php @@ -0,0 +1,218 @@ +<?php +/********************************************************************* + class.user.php + + External end-user identification for osTicket + + Peter Rotich <peter@osticket.com> + Jared Hancock <jared@osticket.com> + Copyright (c) 2006-2013 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: +**********************************************************************/ +require_once(INCLUDE_DIR . 'class.orm.php'); + +class UserEmailModel extends VerySimpleModel { + static $meta = array( + 'table' => USER_EMAIL_TABLE, + 'pk' => array('id'), + 'joins' => array( + 'user' => array( + 'constraint' => array('user_id' => 'UserModel.id') + ) + ) + ); +} + +class UserModel extends VerySimpleModel { + static $meta = array( + 'table' => USER_TABLE, + 'pk' => array('id'), + 'joins' => array( + 'emails' => array( + 'reverse' => 'UserEmailModel.user', + ), + 'default_email' => array( + 'null' => true, + 'constraint' => array('default_email_id' => 'UserEmailModel.id') + ), + ) + ); + + var $emails; + + static function objects() { + $qs = parent::objects(); + #$qs->select_related('default_email'); + return $qs; + } + + function getId() { + return $this->id; + } + + function getDefaultEmailAddress() { + return $this->getDefaultEmail()->address; + } + + function getDefaultEmail() { + return $this->default_email; + } +} + +class User extends UserModel { + + function __construct($ht) { + parent::__construct($ht); + // TODO: Make this automatic with select_related() + if (isset($ht['default_email_id'])) + $this->default_email = UserEmail::lookup($ht['default_email_id']); + } + + static function fromForm($data=false) { + // Try and lookup by email address + $user = User::lookup(array('emails__address'=>$data['email'])); + if (!$user) { + $user = User::create(array('name'=>$data['name'], + 'default_email'=> + UserEmail::create(array('address'=>$data['email'])) + )); + $user->save(); + $user->emails->add($user->default_email); + } + + return $user; + } + + function getEmail() { + return $this->default_email->address; + } + + function getFullName() { + return $this->name; + } + + function getName() { + return new PersonsName($this->name); + } + + function getDynamicData() { + $data = DynamicFormEntry::forClient($this->id); + if (!$data[0]) { + $data = array(); + foreach (UserForm::objects() as $f) { + $g = $f->instanciate(); + $g->setClientId($this->id); + $data[] = $g; + } + } + return $data; + } +} +User::_inspect(); + +class PersonsName { + var $parts; + var $name; + + function __construct($name) { + $this->parts = static::splitName($name); + $this->name = $name; + } + + function getFirst() { + return $this->parts['first']; + } + + function getLast() { + return $this->parts['last']; + } + + function getFormal() { + return trim($this->parts['salutation'].' '.$this->parts['last']); + } + + function getFull() { + return trim($this->parts['first'].' '.$this->parts['last']); + } + + function getComplete() { + return trim($this->parts['salutation'].' '.$this->parts['first'] + .' '.$this->parts['last'].' '.$this->parts['suffix']); + } + + function getLastFirst() { + return $this->parts['last'].', '.$this->parts['first']; + } + + function __toString() { + return $this->getLastFirst(); + } + + /** + * Thanks, http://stackoverflow.com/a/14420217 + */ + static function splitName($name) { + $results = array(); + + // If there is a comma in the name, reverse the name + if (mb_strpos($name, ',' !== false)) { + list($last, $first) = explode(',', $name); + $name = $first.' '.$last; + } + + $r = explode(' ', $name); + $size = count($r); + + //check first for period, assume salutation if so + if (mb_strpos($r[0], '.') === false) + { + $results['salutation'] = ''; + $results['first'] = $r[0]; + } + else + { + $results['salutation'] = $r[0]; + $results['first'] = $r[1]; + } + + //check last for period, assume suffix if so + if (mb_strpos($r[$size - 1], '.') === false) + { + $results['suffix'] = ''; + } + else + { + $results['suffix'] = $r[$size - 1]; + } + + //combine remains into last + $start = ($results['salutation']) ? 2 : 1; + $end = ($results['suffix']) ? $size - 2 : $size - 1; + + $last = ''; + for ($i = $start; $i <= $end; $i++) + { + $last .= ' '.$r[$i]; + } + $results['last'] = trim($last); + + return $results; + } + +} + +class UserEmail extends UserEmailModel { + static function ensure($address) { + $email = static::lookup(array('address'=>$address)); + if (!$email) { + $email = static::create(array('address'=>$address)); + $email->save(); + } + return $email; + } +} diff --git a/include/client/open.inc.php b/include/client/open.inc.php index f39a0ded119c0fbc4d3407b22ed1e340e333b154..ac8a9353d4c585acdd610d65d6d22f8c9d533d04 100644 --- a/include/client/open.inc.php +++ b/include/client/open.inc.php @@ -39,6 +39,7 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):$info; <font class="error">* <?php echo $errors['topicId']; ?></font> </td> </tr> + <?php UserForm::getStaticForm()->render(false, 'Your Information'); ?> </tbody> <tbody id="dynamic-form"> <?php if ($forms) { diff --git a/include/client/tickets.inc.php b/include/client/tickets.inc.php index 81284b2718f05589976e3c484dac1596c42a55a6..04898d5e43e5a27e02907087079e118bb572251a 100644 --- a/include/client/tickets.inc.php +++ b/include/client/tickets.inc.php @@ -18,8 +18,8 @@ if(isset($_REQUEST['status'])) { //Query string status has nothing to do with th $status='open'; //Defaulting to open } -$sortOptions=array('id'=>'ticketID', 'name'=>'ticket.name', 'subject'=>'ticket.subject', - 'email'=>'ticket.email', 'status'=>'ticket.status', 'dept'=>'dept_name','date'=>'ticket.created'); +$sortOptions=array('id'=>'ticketID', 'name'=>'user.name', 'subject'=>'subject.value', + 'email'=>'email.address', 'status'=>'ticket.status', 'dept'=>'dept_name','date'=>'ticket.created'); $orderWays=array('DESC'=>'DESC','ASC'=>'ASC'); //Sorting options... $order_by=$order=null; @@ -39,24 +39,23 @@ $x=$sort.'_sort'; $$x=' class="'.strtolower($order).'" '; $qselect='SELECT ticket.ticket_id,ticket.ticketID,ticket.dept_id,isanswered, ' - .'dept.ispublic, subject.value as subject, name.value as name, email.value as email, ' - .'dept_name,ticket. status, ticket.source, ticket.created '; + .'dept.ispublic, subject.value as subject, ' + .'user.name, email.address as email, ' + .'dept_name,ticket. status, ticket.source, ticket.created '; -$dynfields='(SELECT entry.ticket_id, value FROM '.FORM_ANSWER_TABLE.' ans '. +$dynfields='(SELECT entry.object_id, value 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") %1$s ON ticket.ticket_id = %1$s.ticket_id '; + 'WHERE field.name = "%1$s" entry.object_type="T") %1$s ON ticket.ticket_id = %1$s.ticket_id '; $subject_sql = sprintf($dynfields, 'subject'); -$email_sql = sprintf($dynfields, 'email'); -$name_sql = sprintf($dynfields, 'name'); $qfrom='FROM '.TICKET_TABLE.' ticket ' .' LEFT JOIN '.DEPT_TABLE.' dept ON (ticket.dept_id=dept.dept_id) ' - .' LEFT JOIN '.$subject_sql - .' LEFT JOIN '.$email_sql - .' LEFT JOIN '.$name_sql; + .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id' + .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id' + .' LEFT JOIN '.$subject_sql; -$qwhere =' WHERE email.value='.db_input($thisclient->getEmail()); +$qwhere =' WHERE email.address='.db_input($thisclient->getEmail()); if($status){ $qwhere.=' AND ticket.status='.db_input($status); diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php index 9ce167350272724e1ac96f0fecb0021bd37b467e..4af7cde38f102f5d5ee9e2ad57305b1817c11ed6 100644 --- a/include/staff/dynamic-form.inc.php +++ b/include/staff/dynamic-form.inc.php @@ -55,7 +55,39 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); <thead> <tr> <th colspan="7"> - <em>Form Fields</em> + <em><strong>User Information Fields</strong> more information here</em> + </th> + </tr> + <tr> + <th></th> + <th>Label</th> + <th>Type</th> + <th>Name</th> + <th>Private</th> + <th>Required</th> + </tr> + </thead> + <tbody> + <tr> + <td><input type="checkbox" disabled="disabled"/></td> + <td>Full Name</td><td>Short Answer</td><td>name</td> + <td><input type="checkbox" disabled="disabled"/></td> + <td><input type="checkbox" disabled="disabled" checked="checked"/></td></tr> + <tr> + <td><input type="checkbox" disabled="disabled"/></td> + <td>Email Address</td><td>Short Answer</td><td>email</td> + <td><input type="checkbox" disabled="disabled"/></td> + <td><input type="checkbox" disabled="disabled" checked="checked"/></td></tr> + <tr> + <td><input type="checkbox" disabled="disabled"/></td> + <td>Phone Number</td><td>Phone Number</td><td>phone</td> + <td><input type="checkbox" disabled="disabled"/></td> + <td><input type="checkbox" disabled="disabled"/></td></tr> + </tbody> + <thead> + <tr> + <th colspan="7"> + <em><strong>Form Fields</strong> fields available for ticket information</em> </th> </tr> <tr> diff --git a/include/staff/templates/dynamic-form.tmpl.php b/include/staff/templates/dynamic-form.tmpl.php index 93bb577ea4dfe458c3180ebb4ec67973cc9dcde1..e54d5bfc1395a52fff47f07649aa5b0a3c1646cf 100644 --- a/include/staff/templates/dynamic-form.tmpl.php +++ b/include/staff/templates/dynamic-form.tmpl.php @@ -1,8 +1,10 @@ + <?php if ($form->getTitle()) { ?> <tr><th colspan="2"> <em><strong><?php echo Format::htmlchars($form->getTitle()); ?></strong>: <?php echo Format::htmlchars($form->getInstructions()); ?></em> </th></tr> <?php + } foreach ($form->getFields() as $field) { ?> <tr><td class="multi-line <?php if ($field->get('required')) echo 'required'; ?>"> diff --git a/include/staff/templates/user-info.tmpl.php b/include/staff/templates/user-info.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..b07e19561ab80ca066e756a488965affc529da2a --- /dev/null +++ b/include/staff/templates/user-info.tmpl.php @@ -0,0 +1,36 @@ +<h3>User Information — <?php echo $user->getFullName() ?></h3> +<a class="close" href="">×</a> +<hr/> +<form method="post" action="ajax.php/form/user-info/<?php + echo $user->get('id'); ?>" onsubmit="javascript: + var form = $(this); + $.post(this.action, form.serialize(), function(data, status, xhr) { + if (!data.length) { + form.closest('.dialog').hide(); + $('#overlay').hide(); + } else { + form.closest('.dialog').empty().append(data); + } + }); + return false; + "> + <table width="100%"> + <?php + echo csrf_token(); + $static->render(); + foreach ($custom as $form) + $form->render(); + ?> + </table> + <hr style="margin-top:3em"/> + <p class="full-width"> + <span class="buttons" style="float:left"> + <input type="reset" value="Reset"> + <input type="button" value="Cancel" class="close"> + </span> + <span class="buttons" style="float:right"> + <input type="submit" value="Save"> + </span> + </p> +</form> +<div class="clear"></div> diff --git a/include/staff/ticket-edit.inc.php b/include/staff/ticket-edit.inc.php index 10e042588c3fa04456fd26c9c6e8f715b7b25503..643e147c0bb6e535846038f1a81f99460053afd7 100644 --- a/include/staff/ticket-edit.inc.php +++ b/include/staff/ticket-edit.inc.php @@ -10,14 +10,6 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo()); <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>"> <h2>Update Ticket #<?php echo $ticket->getExtId(); ?></h2> <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> - <thead> - <tr> - <th colspan="2"> - <h4>Ticket Update</h4> - <em><strong>User Information</strong>: Make sure the email address is valid.</em> - </th> - </tr> - </thead> <tbody> <tr> <th colspan="2"> diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index c06117c272285b895b9ce02ccea7eed5d3c6dd3e..e72514b938c083373a151c45559b05dd4721884f 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -17,21 +17,16 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); </tr> </thead> <tbody> - <?php - if($cfg->notifyONNewStaffTicket()) { ?> + <?php + UserForm::getStaticForm()->render(); + if($cfg->notifyONNewStaffTicket()) { ?> <tr> - <th> - <em><strong>User Information</strong></em> - </th> - </tr> <td width="160">Alert:</td> <td> - <input type="checkbox" name="alertuser" <?php echo (!$errors || $info['alertuser'])? 'checked="checked"': ''; ?>>Send alert to user. </td> </tr> - <?php - } ?> + <?php } ?> <tr> <th colspan="2"> <em><strong>Ticket Information & Options</strong>:</em> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index 5b4359c78ec0a17a3fb25eb4b35288dc40c701d7..e99560eb6e8b2c2ecb8f789ecf3a2acb2dad51fc 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -143,29 +143,32 @@ if($ticket->isOverdue()) <td width="50%"> <table border="0" cellspacing="" cellpadding="4" width="100%"> <tr> - <th width="100">Name:</th> - <td><?php echo Format::htmlchars($ticket->getName()); ?></td> - </tr> - <tr> - <th>Email:</th> - <td> - <?php - echo $ticket->getEmail(); + <th width="100">Client:</th> + <td><a href="ajax.php/form/user-info/<?php + echo $ticket->getOwnerId(); ?>" + onclick="javascript: + $('#overlay').show(); + $('#user-info .body').load(this.href); + $('#user-info').show(); + return false; + "><i class="icon-user"></i> <?php + echo Format::htmlchars($ticket->getName()); ?></a> + <?php if(($client=$ticket->getClient())) { - echo sprintf(' <a href="tickets.php?a=search&query=%s" title="Related Tickets" data-dropdown="#action-dropdown-stats">(<b>%d</b>)</a>', - urlencode($ticket->getEmail()), $client->getNumTickets()); + echo sprintf(' <a href="tickets.php?a=search&ownerId=%d" title="Related Tickets" data-dropdown="#action-dropdown-stats">(<b>%d</b>)</a>', + urlencode($ticket->getOwnerId()), $client->getNumTickets()); ?> <div id="action-dropdown-stats" class="action-dropdown anchor-right"> <ul> <?php if(($open=$client->getNumOpenTickets())) - echo sprintf('<li><a href="tickets.php?a=search&status=open&query=%s"><i class="icon-folder-open-alt"></i> %d Open Tickets</a></li>', - $ticket->getEmail(), $open); + echo sprintf('<li><a href="tickets.php?a=search&status=open&ownerId=%s"><i class="icon-folder-open-alt"></i> %d Open Tickets</a></li>', + $ticket->getOwnerId(), $open); if(($closed=$client->getNumClosedTickets())) - echo sprintf('<li><a href="tickets.php?a=search&status=closed&query=%s"><i class="icon-folder-close-alt"></i> %d Closed Tickets</a></li>', - $ticket->getEmail(), $closed); + echo sprintf('<li><a href="tickets.php?a=search&status=closed&ownerId=%d"><i class="icon-folder-close-alt"></i> %d Closed Tickets</a></li>', + $ticket->getOwnerId(), $closed); ?> - <li><a href="tickets.php?a=search&query=<?php echo $ticket->getEmail(); ?>"><i class="icon-double-angle-right"></i> All Tickets</a></li> + <li><a href="tickets.php?a=search&ownerId=<?php echo $ticket->getOwnerId(); ?>"><i class="icon-double-angle-right"></i> All Tickets</a></li> </u> </div> <?php @@ -173,6 +176,12 @@ if($ticket->isOverdue()) ?> </td> </tr> + <tr> + <th>Default Email:</th> + <td> + <?php echo $ticket->getEmail(); ?> + </td> + </tr> <tr> <th>Phone:</th> <td><?php echo $ticket->getPhoneNumber(); ?></td> @@ -447,9 +456,9 @@ if(!$cfg->showNotesInline()) { ?> </td> <td width="765"> <?php - $to = $ticket->getEmail(); + $to = $ticket->getReplyToEmail(); if(($name=$ticket->getName()) && !strpos($name,'@')) - $to =sprintf('%s <em><%s></em>', $name, $ticket->getEmail()); + $to =sprintf('%s <em><%s></em>', $name, $to); echo $to; ?> @@ -821,6 +830,9 @@ if(!$cfg->showNotesInline()) { ?> <?php } ?> </div> +<div style="display:none;" class="dialog" id="user-info"> + <div class="body"></div> +</div> <div style="display:none;" class="dialog" id="print-options"> <h3>Ticket Print Options</h3> <a class="close" href="">×</a> diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index 732c5c277602f44980396d0c293c6a653b058a3f..5d1ea62383fb4cf523b6723e88da82a4afc15d99 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -114,13 +114,17 @@ if($search): }elseif(strpos($searchTerm,'@') && Validator::is_email($searchTerm)){ //pulling all tricks! # XXX: What about searching for email addresses in the body of # the thread message - $qwhere.=" AND email.value='$queryterm'"; + $qwhere.=" AND email.address='$queryterm'"; }else{//Deep search! //This sucks..mass scan! search anything that moves! $deep_search=true; } } + // OwnerId + if ($_REQUEST['ownerId']) { + $qwhere .= ' AND ticket.user_id='.db_input($_REQUEST['ownerId']); + } //department if($_REQUEST['deptId'] && in_array($_REQUEST['deptId'],$thisstaff->getDepts())) { //This is dept based search..perm taken care above..put the sucker in. @@ -237,23 +241,23 @@ $$x=' class="'.strtolower($order).'" '; if($_GET['limit']) $qstr.='&limit='.urlencode($_GET['limit']); -$dynfields='(SELECT entry.ticket_id, value FROM '.FORM_ANSWER_TABLE.' ans '. +$dynfields='(SELECT entry.object_id, value 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")'; + 'WHERE field.name = "%1$s" AND entry.object_type="T")'; $subject_sql=sprintf($dynfields, 'subject'); -$name_sql=sprintf($dynfields, 'name'); -$email_sql=sprintf($dynfields, 'email'); $qselect ='SELECT DISTINCT ticket.ticket_id,lock_id,ticketID,ticket.dept_id,ticket.staff_id,ticket.team_id ' - .' ,subject.value as subject,name.value as name,email.value as email,dept_name ' + .' ,subject.value as subject' + .' ,user.name' + .' ,email.address as email, dept_name ' .' ,ticket.status,ticket.source,isoverdue,isanswered,ticket.created,pri.* '; $qfrom=' 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'. ' LEFT JOIN '.DEPT_TABLE.' dept ON ticket.dept_id=dept.dept_id '. - ' LEFT JOIN '.$subject_sql.' subject ON subject.ticket_id = ticket.ticket_id '. - ' LEFT JOIN '.$name_sql.' name ON name.ticket_id = ticket.ticket_id '. - ' LEFT JOIN '.$email_sql.' email ON email.ticket_id = ticket.ticket_id '; + ' LEFT JOIN '.$subject_sql.' subject ON subject.object_id = ticket.ticket_id'; $sjoin=''; if($search && $deep_search) { diff --git a/main.inc.php b/main.inc.php index 286f3ef11f8038848fa88f38da74a2e9dadbdca4..56da2cb710261bb7fa21c04c700aa9823981f669 100644 --- a/main.inc.php +++ b/main.inc.php @@ -21,6 +21,7 @@ if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwahe require('bootstrap.php'); Bootstrap::loadConfig(); Bootstrap::defineTables(TABLE_PREFIX); +Bootstrap::loadCode(); Bootstrap::connect(); if(!($ost=osTicket::start()) || !($cfg = $ost->getConfig())) diff --git a/open.php b/open.php index 372c338392b5582169ea3e84cf10d46ac6e06027..1d1511c3a70d932e393a743319dc3b16a5a204c7 100644 --- a/open.php +++ b/open.php @@ -31,19 +31,22 @@ if($_POST): } $interest=array('name','email','subject'); - $topic=Topic::lookup($vars['topicId']); - $form=DynamicForm::lookup($topic->ht['form_id'])->instanciate(); - # Collect name, email, and subject address for banning and such - foreach ($form->getAnswers() as $answer) { - $fname = $answer->getField()->get('name'); - if (in_array($fname, $interest)) - # XXX: Assigning to _POST not considered great PHP - # coding style - $vars[$fname] = $answer->getField()->getClean(); + if ($topic=Topic::lookup($vars['topicId'])) { + $form=DynamicForm::lookup($topic->ht['form_id'])->instanciate(); + # Collect name, email, and subject address for banning and such + foreach ($form->getAnswers() as $answer) { + $fname = $answer->getField()->get('name'); + if (in_array($fname, $interest)) + # XXX: Assigning to _POST not considered great PHP + # coding style + $vars[$fname] = $answer->getField()->getClean(); + } + if (!$form->isValid()) + $errors = array_merge($errors, $form->errors()); } - if (!$form->isValid()) - $errors = array_merge($errors, $form->errors()); - + $form2 = UserForm::getStaticForm(); + if (!$form2->isValid()) + $errors += $form2->errors(); if(!$errors && $cfg->allowOnlineAttachments() && $_FILES['attachments']) $vars['files'] = AttachmentFile::format($_FILES['attachments'], true); @@ -52,7 +55,7 @@ if($_POST): $msg='Support ticket request created'; Draft::deleteForNamespace('ticket.client.'.substr(session_id(), -12)); # TODO: Save dynamic form(s) - $form->set('ticket_id', $ticket->getId()); + $form->setTicketId($ticket->getId()); $form->save(); $ticket->loadDynamicData(); //Logged in...simply view the newly created ticket. diff --git a/scp/ajax.php b/scp/ajax.php index 7fae11f1f622b0442bbab3ce3310d7a4cad03750..46fc6385cba5f40b401e5744730bd2763f09dfde 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -48,7 +48,9 @@ $dispatcher = patterns('', url('^/form/', patterns('ajax.forms.php:DynamicFormsAjaxAPI', url_get('^help-topic/(?P<id>\d+)$', 'getFormsForHelpTopic'), url_get('^field-config/(?P<id>\d+)$', 'getFieldConfiguration'), - url_post('^field-config/(?P<id>\d+)$', 'saveFieldConfiguration') + url_post('^field-config/(?P<id>\d+)$', 'saveFieldConfiguration'), + url_get('^user-info/(?P<id>\d+)$', 'getUserInfo'), + url_post('^user-info/(?P<id>\d+)$', 'saveUserInfo') )), url('^/report/overview/', patterns('ajax.reports.php:OverviewReportAjaxAPI', # Send diff --git a/scp/css/scp.css b/scp/css/scp.css index 4fa5ba620bf69d2b35ba45820db1bb9344c41231..8f58ac452a133ffc7b8afd98616a5c81ed9dd366 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -1330,6 +1330,14 @@ time { background-position:bottom left; } +/* Dynamic forms in dialogs */ +.dialog th { + background-color: #eee; + padding: 0.3em; + text-align: left; + padding-left: 1em; +} + #result-count div { padding:5px 10px; text-align:left; diff --git a/scp/tickets.php b/scp/tickets.php index f7ee1ac9c97fb1ffe0586d29d52e27cb0d52f587..296bbc7b273159e7f42127ed0d874d36cc65e97b 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -205,6 +205,7 @@ if($_POST && !$errors): $_REQUEST['a'] = null; //Clear edit action - going back to view. //Check to make sure the staff STILL has access post-update (e.g dept change). foreach ($forms as $f) $f->save(); + $ticket->setOwner($form2->getClean()); if(!$ticket->checkStaffAccess($thisstaff)) $ticket=null; } elseif(!$errors['err']) { @@ -458,19 +459,23 @@ if($_POST && !$errors): case 'open': $ticket=null; $interest=array('name','email','subject'); - $topic=Topic::lookup($_POST['topicId']); - $form=DynamicForm::lookup($topic->ht['form_id']); - $form=$form->instanciate(); - # Collect name, email, and subject address for banning and such - foreach ($form->getAnswers() as $answer) { - $fname = $answer->getField()->get('name'); - if (in_array($fname, $interest)) - # XXX: Assigning to _POST not considered great PHP - # coding style - $_POST[$fname] = $answer->getField()->getClean(); + if ($topic=Topic::lookup($_POST['topicId'])) { + $form = DynamicForm::lookup($topic->ht['form_id']); + $form = $form->instanciate(); + # Collect name, email, and subject address for banning and such + foreach ($form->getAnswers() as $answer) { + $fname = $answer->getField()->get('name'); + if (in_array($fname, $interest)) + # XXX: Assigning to _POST not considered great PHP + # coding style + $_POST[$fname] = $answer->getField()->getClean(); + } + if (!$form->isValid()) + $errors = array_merge($errors, $form->errors()); } - if (!$form->isValid()) - $errors = array_merge($errors, $form->errors()); + $form2 = UserForm::getStaticForm(); + if (!$form2->isValid()) + $errors = array_merge($errors, $form2->errors()); if(!$thisstaff || !$thisstaff->canCreateTickets()) { $errors['err']='You do not have permission to create tickets. Contact admin for such access'; } else { @@ -482,7 +487,7 @@ if($_POST && !$errors): $msg='Ticket created successfully'; $_REQUEST['a']=null; # TODO: Save dynamic form(s) - $form->set('ticket_id', $ticket->getId()); + $form->setTicketId($ticket->getId()); $form->save(); $ticket->loadDynamicData(); if(!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed()) diff --git a/setup/inc/sql/osTicket-mysql.sql b/setup/inc/sql/osTicket-mysql.sql deleted file mode 100644 index 4d613ca612d21adfce466c604b7abd9b35ca5701..0000000000000000000000000000000000000000 --- a/setup/inc/sql/osTicket-mysql.sql +++ /dev/null @@ -1,861 +0,0 @@ - -DROP TABLE IF EXISTS `%TABLE_PREFIX%api_key`; -CREATE TABLE `%TABLE_PREFIX%api_key` ( - `id` int(10) unsigned NOT NULL auto_increment, - `isactive` tinyint(1) NOT NULL default '1', - `ipaddr` varchar(64) NOT NULL, - `apikey` varchar(255) NOT NULL, - `can_create_tickets` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1', - `can_exec_cron` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1', - `notes` text, - `updated` datetime NOT NULL, - `created` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `ipaddr` (`ipaddr`), - UNIQUE KEY `apikey` (`apikey`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%faq`; -CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%faq` ( - `faq_id` int(10) unsigned NOT NULL auto_increment, - `category_id` int(10) unsigned NOT NULL default '0', - `ispublished` tinyint(1) unsigned NOT NULL default '0', - `question` varchar(255) NOT NULL, - `answer` text NOT NULL, - `keywords` tinytext, - `notes` text, - `created` date NOT NULL, - `updated` date NOT NULL, - PRIMARY KEY (`faq_id`), - UNIQUE KEY `question` (`question`), - KEY `category_id` (`category_id`), - KEY `ispublished` (`ispublished`), - FULLTEXT KEY `faq` (`question`,`answer`,`keywords`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%faq_attachment`; -CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%faq_attachment` ( - `faq_id` int(10) unsigned NOT NULL, - `file_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`faq_id`,`file_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%faq_category`; -CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%faq_category` ( - `category_id` int(10) unsigned NOT NULL auto_increment, - `ispublic` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0', - `name` varchar(125) default NULL, - `description` TEXT NOT NULL, - `notes` tinytext NOT NULL, - `created` date NOT NULL, - `updated` date NOT NULL, - PRIMARY KEY (`category_id`), - KEY (`ispublic`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%faq_topic`; -CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%faq_topic` ( - `faq_id` int(10) unsigned NOT NULL, - `topic_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`faq_id`,`topic_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%config`; -CREATE TABLE `%TABLE_PREFIX%config` ( - `id` tinyint(1) unsigned NOT NULL auto_increment, - `isonline` tinyint(1) unsigned NOT NULL default '0', - `timezone_offset` float(3,1) NOT NULL default '0.0', - `enable_daylight_saving` tinyint(1) unsigned NOT NULL default '0', - `staff_ip_binding` tinyint(1) unsigned NOT NULL default '1', - `staff_max_logins` tinyint(3) unsigned NOT NULL default '4', - `staff_login_timeout` int(10) unsigned NOT NULL default '2', - `staff_session_timeout` int(10) unsigned NOT NULL default '30', - `passwd_reset_period` int(10) unsigned NOT NULL default '0', - `client_max_logins` tinyint(3) unsigned NOT NULL default '4', - `client_login_timeout` int(10) unsigned NOT NULL default '2', - `client_session_timeout` int(10) unsigned NOT NULL default '30', - `max_page_size` tinyint(3) unsigned NOT NULL default '25', - `max_open_tickets` tinyint(3) unsigned NOT NULL default '0', - `max_file_size` int(11) unsigned NOT NULL default '1048576', - `max_user_file_uploads` tinyint(3) unsigned NOT NULL, - `max_staff_file_uploads` tinyint(3) unsigned NOT NULL, - `autolock_minutes` tinyint(3) unsigned NOT NULL default '3', - `overdue_grace_period` int(10) unsigned NOT NULL default '0', - `alert_email_id` tinyint(4) unsigned NOT NULL default '0', - `default_email_id` tinyint(4) unsigned NOT NULL default '0', - `default_dept_id` tinyint(3) unsigned NOT NULL default '0', - `default_sla_id` int(10) unsigned NOT NULL default '0', - `default_priority_id` tinyint(2) unsigned NOT NULL default '2', - `default_template_id` tinyint(4) unsigned NOT NULL default '1', - `default_timezone_id` int(10) unsigned NOT NULL default '0', - `default_smtp_id` tinyint(4) unsigned NOT NULL default '0', - `allow_email_spoofing` tinyint(1) unsigned NOT NULL default '0', - `clickable_urls` tinyint(1) unsigned NOT NULL default '1', - `allow_priority_change` tinyint(1) unsigned NOT NULL default '0', - `use_email_priority` tinyint(1) unsigned NOT NULL default '0', - `enable_kb` tinyint(1) unsigned NOT NULL default '0', - `enable_premade` tinyint(1) unsigned NOT NULL default '1', - `enable_captcha` tinyint(1) unsigned NOT NULL default '0', - `enable_auto_cron` tinyint(1) unsigned NOT NULL default '0', - `enable_mail_polling` tinyint(1) unsigned NOT NULL default '0', - `send_sys_errors` tinyint(1) unsigned NOT NULL default '1', - `send_sql_errors` tinyint(1) unsigned NOT NULL default '1', - `send_mailparse_errors` tinyint(1) unsigned NOT NULL default '1', - `send_login_errors` tinyint(1) unsigned NOT NULL default '1', - `save_email_headers` tinyint(1) unsigned NOT NULL default '1', - `strip_quoted_reply` tinyint(1) unsigned NOT NULL default '1', - `log_ticket_activity` tinyint(1) unsigned NOT NULL default '1', - `ticket_autoresponder` tinyint(1) unsigned NOT NULL default '0', - `message_autoresponder` tinyint(1) unsigned NOT NULL default '0', - `ticket_notice_active` tinyint(1) unsigned NOT NULL default '0', - `ticket_alert_active` tinyint(1) unsigned NOT NULL default '0', - `ticket_alert_admin` tinyint(1) unsigned NOT NULL default '1', - `ticket_alert_dept_manager` tinyint(1) unsigned NOT NULL default '1', - `ticket_alert_dept_members` tinyint(1) unsigned NOT NULL default '0', - `message_alert_active` tinyint(1) unsigned NOT NULL default '0', - `message_alert_laststaff` tinyint(1) unsigned NOT NULL default '1', - `message_alert_assigned` tinyint(1) unsigned NOT NULL default '1', - `message_alert_dept_manager` tinyint(1) unsigned NOT NULL default '0', - `note_alert_active` tinyint(1) unsigned NOT NULL default '0', - `note_alert_laststaff` tinyint(1) unsigned NOT NULL default '1', - `note_alert_assigned` tinyint(1) unsigned NOT NULL default '1', - `note_alert_dept_manager` tinyint(1) unsigned NOT NULL default '0', - `transfer_alert_active` tinyint(1) unsigned NOT NULL default '0', - `transfer_alert_assigned` tinyint(1) unsigned NOT NULL default '0', - `transfer_alert_dept_manager` tinyint(1) unsigned NOT NULL default '1', - `transfer_alert_dept_members` tinyint(1) unsigned NOT NULL default '0', - `overdue_alert_active` tinyint(1) unsigned NOT NULL default '0', - `overdue_alert_assigned` tinyint(1) unsigned NOT NULL default '1', - `overdue_alert_dept_manager` tinyint(1) unsigned NOT NULL default '1', - `overdue_alert_dept_members` tinyint(1) unsigned NOT NULL default '0', - `assigned_alert_active` tinyint(1) unsigned NOT NULL default '1', - `assigned_alert_staff` tinyint(1) unsigned NOT NULL default '1', - `assigned_alert_team_lead` tinyint(1) unsigned NOT NULL default '0', - `assigned_alert_team_members` tinyint(1) unsigned NOT NULL default '0', - `auto_assign_reopened_tickets` tinyint(1) unsigned NOT NULL default '1', - `show_related_tickets` tinyint(1) unsigned NOT NULL default '1', - `show_assigned_tickets` tinyint(1) unsigned NOT NULL default '1', - `show_answered_tickets` tinyint(1) unsigned NOT NULL default '0', - `show_notes_inline` tinyint(1) unsigned NOT NULL default '1', - `hide_staff_name` tinyint(1) unsigned NOT NULL default '0', - `overlimit_notice_active` tinyint(1) unsigned NOT NULL default '0', - `email_attachments` tinyint(1) unsigned NOT NULL default '1', - `allow_attachments` tinyint(1) unsigned NOT NULL default '0', - `allow_email_attachments` tinyint(1) unsigned NOT NULL default '0', - `allow_online_attachments` tinyint(1) unsigned NOT NULL default '0', - `allow_online_attachments_onlogin` tinyint(1) unsigned NOT NULL default - '0', - `random_ticket_ids` tinyint(1) unsigned NOT NULL default '1', - `log_level` tinyint(1) unsigned NOT NULL default '2', - `log_graceperiod` int(10) unsigned NOT NULL default '12', - `upload_dir` varchar(255) NOT NULL default '', - `allowed_filetypes` varchar(255) NOT NULL default '.doc, .pdf', - `time_format` varchar(32) NOT NULL default ' h:i A', - `date_format` varchar(32) NOT NULL default 'm/d/Y', - `datetime_format` varchar(60) NOT NULL default 'm/d/Y g:i a', - `daydatetime_format` varchar(60) NOT NULL default 'D, M j Y g:ia', - `reply_separator` varchar(60) NOT NULL default '-- do not edit --', - `admin_email` varchar(125) NOT NULL default '', - `helpdesk_title` varchar(255) NOT NULL default - 'osTicket Support Ticket System', - `helpdesk_url` varchar(255) NOT NULL default '', - `schema_signature` char(32) NOT NULL default '', - `updated` timestamp NOT NULL default CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - KEY `isoffline` (`isonline`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_formset`; -CREATE TABLE `%TABLE_PREFIX%dynamic_formset` ( - `id` int(11) unsigned auto_increment, - `title` varchar(255) NOT NULL, - `instructions` varchar(512), - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_formset_sections`; -CREATE TABLE `%TABLE_PREFIX%dynamic_formset_sections` ( - `id` int(11) unsigned NOT NULL auto_increment, - `formset_id` int(11) NOT NULL, - `section_id` int(11) NOT NULL, - `title` varchar(255), - `instructions` text, - -- Allow more than one form, sorted in this order - `sort` int(11) NOT NULL DEFAULT 1, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_form_section`; -CREATE TABLE `%TABLE_PREFIX%dynamic_form_section` ( - `id` int(11) unsigned NOT NULL auto_increment, - `title` varchar(255) NOT NULL, - `instructions` varchar(512), - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_form_field`; -CREATE TABLE `%TABLE_PREFIX%dynamic_form_field` ( - `id` int(11) unsigned NOT NULL auto_increment, - `section_id` int(11) unsigned NOT NULL, - `type` varchar(255) NOT NULL DEFAULT 'text', - `label` varchar(255) NOT NULL, - `required` tinyint(1) NOT NULL DEFAULT 0, - `private` tinyint(1) NOT NULL DEFAULT 0, - `name` varchar(64) NOT NULL, - `configuration` text, - `sort` int(11) unsigned NOT NULL, - `hint` varchar(512), - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- Create a default form to mimic the previous default form of osTicket < 1.7.1 -INSERT INTO `%TABLE_PREFIX%dynamic_form_section` SET - `id` = 1, `title` = 'User Information', `created` = NOW(), - `updated` = NOW(); -INSERT INTO `%TABLE_PREFIX%dynamic_form_section` SET - `id` = 2, `title` = 'Ticket Details', `created` = NOW(), - `updated` = NOW(); - -INSERT INTO `%TABLE_PREFIX%dynamic_formset` SET - `id` = 1, `title` = 'Default', `created` = NOW(), `updated` = NOW(); - -INSERT INTO `%TABLE_PREFIX%dynamic_formset_sections` SET - `formset_id` = 1, `section_id` = 1, `sort` = 10; -INSERT INTO `%TABLE_PREFIX%dynamic_formset_sections` SET - `formset_id` = 1, `section_id` = 2, `sort` = 20; - -INSERT INTO `%TABLE_PREFIX%dynamic_form_field` SET - `section_id` = 1, `type` = 'text', `label` = 'Email Address', - `required` = 1, `configuration` = '{"size":40,"length":40,"validator":"email"}', - `name` = 'email', `sort` = 10, `created` = NOW(), `updated` = NOW(); -INSERT INTO `%TABLE_PREFIX%dynamic_form_field` SET - `section_id` = 1, `type` = 'text', `label` = 'Full Name', - `required` = 1, `configuration` = '{"size":40,"length":40}', - `name` = 'name', `sort` = 20, `created` = NOW(), `updated` = NOW(); -INSERT INTO `%TABLE_PREFIX%dynamic_form_field` SET - `section_id` = 1, `type` = 'phone', `label` = 'Phone Number', - `name` = 'phone', `sort` = 30, `created` = NOW(), `updated` = NOW(); - -INSERT INTO `%TABLE_PREFIX%dynamic_form_field` SET - `section_id` = 2, `type` = 'text', `label` = 'Subject', - `hint` = 'Issue summary', `required` = 1, - `configuration` = '{"size":40,"length":50}', - `name` = 'subject', `sort` = 10, `created` = NOW(), `updated` = NOW(); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_form_entry`; -CREATE TABLE `%TABLE_PREFIX%dynamic_form_entry` ( - `id` int(11) unsigned NOT NULL auto_increment, - `section_id` int(11) unsigned NOT NULL, - `ticket_id` int(11) unsigned, - `sort` int(11) unsigned NOT NULL DEFAULT 1, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `ticket_dyn_form_lookup` (`ticket_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_form_entry_values`; -CREATE TABLE `%TABLE_PREFIX%dynamic_form_entry_values` ( - -- references dynamic_form_entry.id - `entry_id` int(11) unsigned NOT NULL, - `field_id` int(11) unsigned NOT NULL, - `value` text, - PRIMARY KEY (`entry_id`, `field_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_list`; -CREATE TABLE `%TABLE_PREFIX%dynamic_list` ( - `id` int(11) unsigned NOT NULL auto_increment, - `name` varchar(255) NOT NULL, - `name_plural` varchar(255), - `sort_mode` enum('Alpha', '-Alpha', 'SortCol') NOT NULL DEFAULT 'Alpha', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%dynamic_list_items`; -CREATE TABLE `%TABLE_PREFIX%dynamic_list_items` ( - `id` int(11) unsigned NOT NULL auto_increment, - `list_id` int(11), - `value` varchar(255) NOT NULL, - -- extra value such as abbreviation - `extra` varchar(255), - `sort` int(11) NOT NULL DEFAULT 1, - PRIMARY KEY (`id`), - KEY `dynamic_list_item_lookup` (`list_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%department`; -CREATE TABLE `%TABLE_PREFIX%department` ( - `dept_id` int(11) unsigned NOT NULL auto_increment, - `tpl_id` int(10) unsigned NOT NULL default '0', - `sla_id` int(10) unsigned NOT NULL default '0', - `email_id` int(10) unsigned NOT NULL default '0', - `autoresp_email_id` int(10) unsigned NOT NULL default '0', - `manager_id` int(10) unsigned NOT NULL default '0', - `dept_name` varchar(128) NOT NULL default '', - `dept_signature` tinytext NOT NULL, - `ispublic` tinyint(1) unsigned NOT NULL default '1', - `group_membership` tinyint(1) NOT NULL default '0', - `ticket_auto_response` tinyint(1) NOT NULL default '1', - `message_auto_response` tinyint(1) NOT NULL default '0', - `updated` datetime NOT NULL, - `created` datetime NOT NULL, - PRIMARY KEY (`dept_id`), - UNIQUE KEY `dept_name` (`dept_name`), - KEY `manager_id` (`manager_id`), - KEY `autoresp_email_id` (`autoresp_email_id`), - KEY `tpl_id` (`tpl_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%department` (`dept_id`, `tpl_id`, `sla_id`, `email_id`, `autoresp_email_id`, `manager_id`, `dept_name`, `dept_signature`, `ispublic`, `ticket_auto_response`, `message_auto_response`) VALUES - (1, 0, 0, 1, 1, 0, 'Support', 'Support Dept', 1, 1, 1), - (2, 0, 1, 1, 1, 0, 'Billing', 'Billing Dept', 1, 1, 1); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%email`; -CREATE TABLE `%TABLE_PREFIX%email` ( - `email_id` int(11) unsigned NOT NULL auto_increment, - `noautoresp` tinyint(1) unsigned NOT NULL default '0', - `priority_id` tinyint(3) unsigned NOT NULL default '2', - `dept_id` tinyint(3) unsigned NOT NULL default '0', - `email` varchar(255) NOT NULL default '', - `name` varchar(255) NOT NULL default '', - `userid` varchar(255) NOT NULL, - `userpass` varchar(125) NOT NULL, - `mail_active` tinyint(1) NOT NULL default '0', - `mail_host` varchar(255) NOT NULL, - `mail_protocol` enum('POP','IMAP') NOT NULL default 'POP', - `mail_encryption` enum('NONE','SSL') NOT NULL, - `mail_port` int(6) default NULL, - `mail_fetchfreq` tinyint(3) NOT NULL default '5', - `mail_fetchmax` tinyint(4) NOT NULL default '30', - `mail_archivefolder` varchar(255) default NULL, - `mail_delete` tinyint(1) NOT NULL default '0', - `mail_errors` tinyint(3) NOT NULL default '0', - `mail_lasterror` datetime default NULL, - `mail_lastfetch` datetime default NULL, - `smtp_active` tinyint(1) default '0', - `smtp_host` varchar(255) NOT NULL, - `smtp_port` int(6) default NULL, - `smtp_secure` tinyint(1) NOT NULL default '1', - `smtp_auth` tinyint(1) NOT NULL default '1', - `smtp_spoofing` tinyint(1) unsigned NOT NULL default '0', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`email_id`), - UNIQUE KEY `email` (`email`), - KEY `priority_id` (`priority_id`), - KEY `dept_id` (`dept_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%filter`; -CREATE TABLE `%TABLE_PREFIX%filter` ( - `id` int(11) unsigned NOT NULL auto_increment, - `execorder` int(10) unsigned NOT NULL default '99', - `isactive` tinyint(1) unsigned NOT NULL default '1', - `match_all_rules` tinyint(1) unsigned NOT NULL default '0', - `stop_onmatch` tinyint(1) unsigned NOT NULL default '0', - `reject_ticket` tinyint(1) unsigned NOT NULL default '0', - `use_replyto_email` tinyint(1) unsigned NOT NULL default '0', - `disable_autoresponder` tinyint(1) unsigned NOT NULL default '0', - `canned_response_id` int(11) unsigned NOT NULL default '0', - `email_id` int(10) unsigned NOT NULL default '0', - `priority_id` int(10) unsigned NOT NULL default '0', - `dept_id` int(10) unsigned NOT NULL default '0', - `staff_id` int(10) unsigned NOT NULL default '0', - `team_id` int(10) unsigned NOT NULL default '0', - `sla_id` int(10) unsigned NOT NULL default '0', - `target` ENUM( 'Any', 'Web', 'Email', 'API' ) NOT NULL DEFAULT 'Any', - `name` varchar(32) NOT NULL default '', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `target` (`target`), - KEY `email_id` (`email_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -INSERT INTO `%TABLE_PREFIX%filter` ( - `id`,`isactive`,`execorder`,`reject_ticket`,`name`,`notes`,`created`) - VALUES (1, 1, 99, 1, 'SYSTEM BAN LIST', 'Internal list for email banning. Do not remove', NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%filter_rule`; -CREATE TABLE `%TABLE_PREFIX%filter_rule` ( - `id` int(11) unsigned NOT NULL auto_increment, - `filter_id` int(10) unsigned NOT NULL default '0', - `what` enum('name','email','subject','body','header') NOT NULL, - `how` enum('equal','not_equal','contains','dn_contain','starts','ends') NOT NULL, - `val` varchar(255) NOT NULL, - `isactive` tinyint(1) unsigned NOT NULL DEFAULT '1', - `notes` tinytext NOT NULL, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `filter_id` (`filter_id`), - UNIQUE `filter` (`filter_id`, `what`, `how`, `val`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%filter_rule` ( - `id`, `filter_id`, `isactive`, `what`,`how`,`val`,`created`) - VALUES (1, 1, 1, 'email', 'equal', 'test@example.com',NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%email_template`; -CREATE TABLE `%TABLE_PREFIX%email_template` ( - `tpl_id` int(11) NOT NULL auto_increment, - `cfg_id` int(10) unsigned NOT NULL default '0', - `isactive` tinyint(1) unsigned NOT NULL default '0', - `name` varchar(32) NOT NULL default '', - `notes` text, - `ticket_autoresp_subj` varchar(255) NOT NULL default '', - `ticket_autoresp_body` text NOT NULL, - `ticket_autoreply_subj` varchar(255) NOT NULL default '', - `ticket_autoreply_body` text NOT NULL, - `ticket_notice_subj` varchar(255) NOT NULL, - `ticket_notice_body` text NOT NULL, - `ticket_alert_subj` varchar(255) NOT NULL default '', - `ticket_alert_body` text NOT NULL, - `message_autoresp_subj` varchar(255) NOT NULL default '', - `message_autoresp_body` text NOT NULL, - `message_alert_subj` varchar(255) NOT NULL default '', - `message_alert_body` text NOT NULL, - `note_alert_subj` varchar(255) NOT NULL, - `note_alert_body` text NOT NULL, - `assigned_alert_subj` varchar(255) NOT NULL default '', - `assigned_alert_body` text NOT NULL, - `transfer_alert_subj` varchar(255) NOT NULL default '', - `transfer_alert_body` text NOT NULL, - `ticket_overdue_subj` varchar(255) NOT NULL default '', - `ticket_overdue_body` text NOT NULL, - `ticket_overlimit_subj` varchar(255) NOT NULL default '', - `ticket_overlimit_body` text NOT NULL, - `ticket_reply_subj` varchar(255) NOT NULL default '', - `ticket_reply_body` text NOT NULL, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`tpl_id`), - KEY `cfg_id` (`cfg_id`), - FULLTEXT KEY `message_subj` (`ticket_reply_subj`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- TODO: Dump revised copy before release!!! -INSERT INTO `%TABLE_PREFIX%email_template` (`tpl_id`, `cfg_id`, `isactive`, `name`, `notes`, `ticket_autoresp_subj`, `ticket_autoresp_body`, `ticket_autoreply_subj`, `ticket_autoreply_body`, `ticket_notice_subj`, `ticket_notice_body`, `ticket_alert_subj`, `ticket_alert_body`, `message_autoresp_subj`, `message_autoresp_body`, `message_alert_subj`, `message_alert_body`, `note_alert_subj`, `note_alert_body`, `assigned_alert_subj`, `assigned_alert_body`, `transfer_alert_subj`, `transfer_alert_body`, `ticket_overdue_subj`, `ticket_overdue_body`, `ticket_overlimit_subj`, `ticket_overlimit_body`, `ticket_reply_subj`, `ticket_reply_body`, `created`, `updated`) VALUES -(1, 1, 1, 'osTicket Default Template', 'Default osTicket templates', 'Support Ticket Opened [#%{ticket.number}]', '%{ticket.name},\r\n\r\nA request for support has been created and assigned ticket #%{ticket.number}. A representative will follow-up with you as soon as possible.\r\n\r\nYou can view this ticket''s progress online here: %{ticket.client_link}.\r\n\r\nIf you wish to send additional comments or information regarding this issue, please don''t open a new ticket. Simply login using the link above and update the ticket.\r\n\r\n%{signature}', 'Support Ticket Opened [#%{ticket.number}]', '%{ticket.name},\r\n\r\nA request for support has been created and assigned ticket #%{ticket.number} with the following auto-reply:\r\n\r\n%{response}\r\n\r\n\r\nWe hope this response has sufficiently answered your questions. If not, please do not open another ticket. If need be, representative will follow-up with you as soon as possible.\r\n\r\nYou can view this ticket''s progress online here: %{ticket.client_link}.', '[#%{ticket.number}] %{ticket.subject}', '%{ticket.name},\r\n\r\nOur customer care team has created a ticket, #%{ticket.number} on your behalf, with the following message.\r\n\r\n%{message}\r\n\r\nIf you wish to provide additional comments or information regarding this issue, please don''t open a new ticket. You can update or view this ticket''s progress online here: %{ticket.client_link}.\r\n\r\n%{signature}', 'New Ticket Alert', '%{recipient},\r\n\r\nNew ticket #%{ticket.number} created.\r\n\r\n-----------------------\r\nName: %{ticket.name}\r\nEmail: %{ticket.email}\r\nDept: %{ticket.dept.name}\r\n\r\n%{message}\r\n-----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.', '[#%{ticket.number}] Message Added', '%{ticket.name},\r\n\r\nYour reply to support request #%{ticket.number} has been noted.\r\n\r\nYou can view this support request progress online here: %{ticket.client_link}.\r\n\r\n%{signature}', 'New Message Alert', '%{recipient},\r\n\r\nNew message appended to ticket #%{ticket.number}\r\n\r\n----------------------\r\nName: %{ticket.name}\r\nEmail: %{ticket.email}\r\nDept: %{ticket.dept.name}\r\n\r\n%{message}\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.', 'New Internal Note Alert', '%{recipient},\r\n\r\nInternal note appended to ticket #%{ticket.number}\r\n\r\n----------------------\r\n* %{note.title} *\r\n\r\n%{note.message}\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.', 'Ticket #%{ticket.number} Assigned to you', '%{assignee},\r\n\r\nTicket #%{ticket.number} has been assigned to you by %{assigner}\r\n\r\n----------------------\r\n\r\n%{comments}\r\n\r\n----------------------\r\n\r\nTo view complete details, simply login to the support system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Support Ticket System - powered by osTicket.', 'Ticket Transfer #%{ticket.number} - %{ticket.dept.name}', '%{recipient},\r\n\r\nTicket #%{ticket.number} has been transferred to %{ticket.dept.name} department by %{staff.name}\r\n\r\n----------------------\r\n\r\n%{comments}\r\n\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.', 'Stale Ticket Alert', '%{recipient},\r\n\r\nA ticket, #%{ticket.number} assigned to you or in your department is seriously overdue.\r\n\r\n%{ticket.staff_link}\r\n\r\nWe should all work hard to guarantee that all tickets are being addressed in a timely manner.\r\n\r\n- Your friendly (although with limited patience) Support Ticket System - powered by osTicket.', 'Open Tickets Limit Reached', '%{ticket.name}\r\n\r\nYou have reached the maximum number of open tickets allowed.\r\n\r\nTo be able to open another ticket, one of your pending tickets must be closed. To update or add comments to an open ticket simply login using the link below.\r\n\r\n%{url}/tickets.php?e=%{ticket.email}\r\n\r\nThank you.\r\n\r\nSupport Ticket System', '[#%{ticket.number}] %{ticket.subject}', '%{ticket.name},\r\n\r\nA customer support staff member has replied to your support request, #%{ticket.number} with the following response:\r\n\r\n%{response}\r\n\r\nWe hope this response has sufficiently answered your questions. If not, please do not send another email. Instead, reply to this email or login to your account for a complete archive of all your support requests and responses.\r\n\r\n%{ticket.client_link}\r\n\r\n%{signature}', NOW(), NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%file`; -CREATE TABLE `%TABLE_PREFIX%file` ( - `id` int(11) NOT NULL auto_increment, - `type` varchar(255) NOT NULL default '', - `size` varchar(25) NOT NULL default '', - `hash` varchar(125) NOT NULL, - `name` varchar(255) NOT NULL default '', - `created` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `hash` (`hash`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%file` (`id`, `type`, `size`, `hash`, `name`, `created`) VALUES -(1, 'text/plain', '25', '670c6cc1d1dfc97fad20e5470251b255', 'osTicket.txt', NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%file_chunk`; -CREATE TABLE `%TABLE_PREFIX%file_chunk` ( - `file_id` int(11) NOT NULL, - `chunk_id` int(11) NOT NULL, - `filedata` longblob NOT NULL, - PRIMARY KEY (`file_id`, `chunk_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%file_chunk` (`file_id`, `chunk_id`, `filedata`) -VALUES (1, 0, 0x43616e6e6564206174746163686d656e747320726f636b210a); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%groups`; -CREATE TABLE `%TABLE_PREFIX%groups` ( - `group_id` int(10) unsigned NOT NULL auto_increment, - `group_enabled` tinyint(1) unsigned NOT NULL default '1', - `group_name` varchar(50) NOT NULL default '', - `can_create_tickets` tinyint(1) unsigned NOT NULL default '1', - `can_edit_tickets` tinyint(1) unsigned NOT NULL default '1', - `can_post_ticket_reply` tinyint( 1 ) unsigned NOT NULL DEFAULT '1', - `can_delete_tickets` tinyint(1) unsigned NOT NULL default '0', - `can_close_tickets` tinyint(1) unsigned NOT NULL default '1', - `can_assign_tickets` tinyint(1) unsigned NOT NULL default '1', - `can_transfer_tickets` tinyint(1) unsigned NOT NULL default '1', - `can_ban_emails` tinyint(1) unsigned NOT NULL default '0', - `can_manage_premade` tinyint(1) unsigned NOT NULL default '0', - `can_manage_faq` tinyint(1) unsigned NOT NULL default '0', - `can_view_staff_stats` tinyint( 1 ) unsigned NOT NULL DEFAULT '0', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`group_id`), - KEY `group_active` (`group_enabled`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%groups` (`group_id`, `group_enabled`, `group_name`, `can_create_tickets`, `can_edit_tickets`, `can_delete_tickets`, `can_close_tickets`, `can_assign_tickets`, `can_transfer_tickets`, `can_ban_emails`, `can_manage_premade`, `can_manage_faq`, `notes`, `created`, `updated`) VALUES - (1, 1, 'Admins', 1, 1, 1, 1, 1, 1, 1, 1, 1, 'overlords', NOW(), NOW()), - (2, 1, 'Managers', 1, 1, 1, 1, 1, 1, 1, 1, 1, '', NOW(), NOW()), - (3, 1, 'Staff', 1, 1, 0, 1, 1, 1, 0, 0, 0, '', NOW(), NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%group_dept_access`; -CREATE TABLE `%TABLE_PREFIX%group_dept_access` ( - `group_id` int(10) unsigned NOT NULL default '0', - `dept_id` int(10) unsigned NOT NULL default '0', - UNIQUE KEY `group_dept` (`group_id`,`dept_id`), - KEY `dept_id` (`dept_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%group_dept_access` (`group_id`, `dept_id`) VALUES - (1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%help_topic`; -CREATE TABLE `%TABLE_PREFIX%help_topic` ( - `topic_id` int(11) unsigned NOT NULL auto_increment, - `topic_pid` int(10) unsigned NOT NULL default '0', - `isactive` tinyint(1) unsigned NOT NULL default '1', - `ispublic` tinyint(1) unsigned NOT NULL default '1', - `noautoresp` tinyint(3) unsigned NOT NULL default '0', - `priority_id` tinyint(3) unsigned NOT NULL default '0', - `dept_id` tinyint(3) unsigned NOT NULL default '0', - `staff_id` int(10) unsigned NOT NULL default '0', - `team_id` int(10) unsigned NOT NULL default '0', - `sla_id` int(10) unsigned NOT NULL default '0', - `formset_id` int(11) unsigned NOT NULL default '0', - `topic` varchar(32) NOT NULL default '', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`topic_id`), - UNIQUE KEY `topic` ( `topic` , `topic_pid` ), - KEY `topic_pid` (`topic_pid`), - KEY `priority_id` (`priority_id`), - KEY `dept_id` (`dept_id`), - KEY `staff_id` (`staff_id`,`team_id`), - KEY `sla_id` (`sla_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%help_topic` (`topic_id`, `isactive`, `ispublic`, - `noautoresp`, `priority_id`, `dept_id`, `staff_id`, `team_id`, - `sla_id`, `formset_id`, `topic`, `notes`) VALUES - (1, 1, 1, 0, 2, 1, 0, 0, 1, 1, 'Support', NULL), - (2, 1, 1, 0, 3, 1, 0, 0, 0, 1, 'Billing', NULL); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%canned_response`; -CREATE TABLE `%TABLE_PREFIX%canned_response` ( - `canned_id` int(10) unsigned NOT NULL auto_increment, - `dept_id` int(10) unsigned NOT NULL default '0', - `isenabled` tinyint(1) unsigned NOT NULL default '1', - `title` varchar(255) NOT NULL default '', - `response` text NOT NULL, - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`canned_id`), - UNIQUE KEY `title` (`title`), - KEY `dept_id` (`dept_id`), - KEY `active` (`isenabled`), - FULLTEXT KEY `resp` (`title`,`response`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%canned_response` (`canned_id`, `dept_id`, `isenabled`, `title`, `response`) VALUES - (1, 0, 1, 'What is osTicket (sample)?', '\r\nosTicket is a widely-used open source support ticket system, an attractive alternative to higher-cost and complex customer support systems - simple, lightweight, reliable, open source, web-based and easy to setup and use.'), - (2, 0, 1, 'Sample (with variables)', '\r\n%{ticket.name},\r\n\r\nYour ticket #%{ticket.number} created on %{ticket.create_date} is in %{ticket.dept.name} department.\r\n\r\n'); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%canned_attachment`; -CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%canned_attachment` ( - `canned_id` int(10) unsigned NOT NULL, - `file_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`canned_id`,`file_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%canned_attachment` (`canned_id`, `file_id`) VALUES (1,1); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%session`; -CREATE TABLE `%TABLE_PREFIX%session` ( - `session_id` varchar(256) collate utf8_unicode_ci NOT NULL default '', - `session_data` longtext collate utf8_unicode_ci, - `session_expire` datetime default NULL, - `session_updated` datetime default NULL, - `user_id` int(10) unsigned NOT NULL default '0' COMMENT 'osTicket staff ID', - `user_ip` varchar(64) NOT NULL, - `user_agent` varchar(255) collate utf8_unicode_ci NOT NULL, - PRIMARY KEY (`session_id`), - KEY `updated` (`session_updated`), - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%sla`; -CREATE TABLE `%TABLE_PREFIX%sla` ( - `id` int(11) unsigned NOT NULL auto_increment, - `isactive` tinyint(1) unsigned NOT NULL default '1', - `enable_priority_escalation` tinyint(1) unsigned NOT NULL default '1', - `disable_overdue_alerts` tinyint(1) unsigned NOT NULL default '0', - `grace_period` int(10) unsigned NOT NULL default '0', - `name` varchar(64) NOT NULL default '', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%sla` (`isactive`, `enable_priority_escalation`, - `disable_overdue_alerts`, `grace_period`, `name`, `notes`, `created`, `updated`) - VALUES (1, 1, 0, 48, 'Default SLA', NULL, NOW(), NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%staff`; -CREATE TABLE `%TABLE_PREFIX%staff` ( - `staff_id` int(11) unsigned NOT NULL auto_increment, - `group_id` int(10) unsigned NOT NULL default '0', - `dept_id` int(10) unsigned NOT NULL default '0', - `timezone_id` int(10) unsigned NOT NULL default '0', - `username` varchar(32) NOT NULL default '', - `firstname` varchar(32) default NULL, - `lastname` varchar(32) default NULL, - `passwd` varchar(128) default NULL, - `email` varchar(128) default NULL, - `phone` varchar(24) NOT NULL default '', - `phone_ext` varchar(6) default NULL, - `mobile` varchar(24) NOT NULL default '', - `signature` tinytext NOT NULL, - `notes` text, - `isactive` tinyint(1) NOT NULL default '1', - `isadmin` tinyint(1) NOT NULL default '0', - `isvisible` tinyint(1) unsigned NOT NULL default '1', - `onvacation` tinyint(1) unsigned NOT NULL default '0', - `assigned_only` tinyint(1) unsigned NOT NULL default '0', - `show_assigned_tickets` tinyint(1) unsigned NOT NULL default '0', - `daylight_saving` tinyint(1) unsigned NOT NULL default '0', - `change_passwd` tinyint(1) unsigned NOT NULL default '0', - `max_page_size` int(11) unsigned NOT NULL default '0', - `auto_refresh_rate` int(10) unsigned NOT NULL default '0', - `default_signature_type` ENUM( 'none', 'mine', 'dept' ) NOT NULL DEFAULT 'none', - `default_paper_size` ENUM( 'Letter', 'Legal', 'Ledger', 'A4', 'A3' ) NOT NULL DEFAULT 'Letter', - `created` datetime NOT NULL, - `lastlogin` datetime default NULL, - `passwdreset` datetime default NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`staff_id`), - UNIQUE KEY `username` (`username`), - KEY `dept_id` (`dept_id`), - KEY `issuperuser` (`isadmin`), - KEY `group_id` (`group_id`,`staff_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%syslog`; -CREATE TABLE `%TABLE_PREFIX%syslog` ( - `log_id` int(11) unsigned NOT NULL auto_increment, - `log_type` enum('Debug','Warning','Error') NOT NULL, - `title` varchar(255) NOT NULL, - `log` text NOT NULL, - `logger` varchar(64) NOT NULL, - `ip_address` varchar(64) NOT NULL, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`log_id`), - KEY `log_type` (`log_type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%team`; -CREATE TABLE `%TABLE_PREFIX%team` ( - `team_id` int(10) unsigned NOT NULL auto_increment, - `lead_id` int(10) unsigned NOT NULL default '0', - `isenabled` tinyint(1) unsigned NOT NULL default '1', - `noalerts` tinyint(1) unsigned NOT NULL default '0', - `name` varchar(125) NOT NULL default '', - `notes` text, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`team_id`), - UNIQUE KEY `name` (`name`), - KEY `isnabled` (`isenabled`), - KEY `lead_id` (`lead_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%team` (`lead_id`, `isenabled`, `noalerts`, `name`, `notes`, `created`, `updated`) - VALUES (0, 1, 0, 'Level I Support', '', NOW(), NOW()); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%team_member`; -CREATE TABLE `%TABLE_PREFIX%team_member` ( - `team_id` int(10) unsigned NOT NULL default '0', - `staff_id` int(10) unsigned NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`team_id`,`staff_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket`; -CREATE TABLE `%TABLE_PREFIX%ticket` ( - `ticket_id` int(11) unsigned NOT NULL auto_increment, - `ticketID` int(11) unsigned NOT NULL default '0', - `dept_id` int(10) unsigned NOT NULL default '1', - `sla_id` int(10) unsigned NOT NULL default '0', - `priority_id` int(10) unsigned NOT NULL default '2', - `topic_id` int(10) unsigned NOT NULL default '0', - `staff_id` int(10) unsigned NOT NULL default '0', - `team_id` int(10) unsigned NOT NULL default '0', - `ip_address` varchar(64) NOT NULL default '', - `status` enum('open','closed') NOT NULL default 'open', - `source` enum('Web','Email','Phone','API','Other') NOT NULL default -'Other', - `isoverdue` tinyint(1) unsigned NOT NULL default '0', - `isanswered` tinyint(1) unsigned NOT NULL default '0', - `duedate` datetime default NULL, - `reopened` datetime default NULL, - `closed` datetime default NULL, - `lastmessage` datetime default NULL, - `lastresponse` datetime default NULL, - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`ticket_id`), - KEY `dept_id` (`dept_id`), - KEY `staff_id` (`staff_id`), - KEY `team_id` (`staff_id`), - KEY `status` (`status`), - KEY `priority_id` (`priority_id`), - KEY `created` (`created`), - KEY `closed` (`closed`), - KEY `duedate` (`duedate`), - KEY `topic_id` (`topic_id`), - KEY `sla_id` (`sla_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_attachment`; -CREATE TABLE `%TABLE_PREFIX%ticket_attachment` ( - `attach_id` int(11) unsigned NOT NULL auto_increment, - `ticket_id` int(11) unsigned NOT NULL default '0', - `file_id` int(10) unsigned NOT NULL default '0', - `ref_id` int(11) unsigned NOT NULL default '0', - `ref_type` enum('M','R','N') NOT NULL default 'M', - `created` datetime NOT NULL, - PRIMARY KEY (`attach_id`), - KEY `ticket_id` (`ticket_id`), - KEY `ref_type` (`ref_type`), - KEY `ref_id` (`ref_id`), - KEY `file_id` (`file_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_lock`; -CREATE TABLE `%TABLE_PREFIX%ticket_lock` ( - `lock_id` int(11) unsigned NOT NULL auto_increment, - `ticket_id` int(11) unsigned NOT NULL default '0', - `staff_id` int(10) unsigned NOT NULL default '0', - `expire` datetime default NULL, - `created` datetime NOT NULL, - PRIMARY KEY (`lock_id`), - UNIQUE KEY `ticket_id` (`ticket_id`), - KEY `staff_id` (`staff_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_email_info`; -CREATE TABLE `%TABLE_PREFIX%ticket_email_info` ( - `message_id` int(11) unsigned NOT NULL, - `email_mid` varchar(255) NOT NULL, - `headers` text, - KEY `message_id` (`email_mid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_event`; -CREATE TABLE `%TABLE_PREFIX%ticket_event` ( - `ticket_id` int(11) unsigned NOT NULL default '0', - `staff_id` int(11) unsigned NOT NULL, - `team_id` int(11) unsigned NOT NULL, - `dept_id` int(11) unsigned NOT NULL, - `topic_id` int(11) unsigned NOT NULL, - `state` enum('created','closed','reopened','assigned','transferred','overdue') NOT NULL, - `staff` varchar(255) NOT NULL default 'SYSTEM', - `annulled` tinyint(1) unsigned NOT NULL default '0', - `timestamp` datetime NOT NULL, - KEY `ticket_state` (`ticket_id`, `state`, `timestamp`), - KEY `ticket_stats` (`timestamp`, `state`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_priority`; -CREATE TABLE `%TABLE_PREFIX%ticket_priority` ( - `priority_id` tinyint(4) NOT NULL auto_increment, - `priority` varchar(60) NOT NULL default '', - `priority_desc` varchar(30) NOT NULL default '', - `priority_color` varchar(7) NOT NULL default '', - `priority_urgency` tinyint(1) unsigned NOT NULL default '0', - `ispublic` tinyint(1) NOT NULL default '1', - PRIMARY KEY (`priority_id`), - UNIQUE KEY `priority` (`priority`), - KEY `priority_urgency` (`priority_urgency`), - KEY `ispublic` (`ispublic`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%ticket_priority` (`priority_id`, `priority`, `priority_desc`, `priority_color`, `priority_urgency`, `ispublic`) VALUES - (1, 'low', 'Low', '#DDFFDD', 4, 1), - (2, 'normal', 'Normal', '#FFFFF0', 3, 1), - (3, 'high', 'High', '#FEE7E7', 2, 1), - (4, 'emergency', 'Emergency', '#FEE7E7', 1, 0); - -DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_thread`; -CREATE TABLE `%TABLE_PREFIX%ticket_thread` ( - `id` int(11) unsigned NOT NULL auto_increment, - `pid` int(11) unsigned NOT NULL default '0', - `ticket_id` int(11) unsigned NOT NULL default '0', - `staff_id` int(11) unsigned NOT NULL default '0', - `thread_type` enum('M','R','N') NOT NULL, - `poster` varchar(128) NOT NULL default '', - `source` varchar(32) NOT NULL default '', - `title` varchar(255), - `body` text NOT NULL, - `ip_address` varchar(64) NOT NULL default '', - `created` datetime NOT NULL, - `updated` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `ticket_id` (`ticket_id`), - KEY `staff_id` (`staff_id`), - KEY `pid` (`pid`), - FULLTEXT KEY `body` (`body`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `%TABLE_PREFIX%timezone`; -CREATE TABLE `%TABLE_PREFIX%timezone` ( - `id` int(11) unsigned NOT NULL auto_increment, - `offset` float(3,1) NOT NULL default '0.0', - `timezone` varchar(255) NOT NULL default '', - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `%TABLE_PREFIX%timezone` (`id`, `offset`, `timezone`) VALUES -(1, -12.0, 'Eniwetok, Kwajalein'), -(2, -11.0, 'Midway Island, Samoa'), -(3, -10.0, 'Hawaii'), -(4, -9.0, 'Alaska'), -(5, -8.0, 'Pacific Time (US & Canada)'), -(6, -7.0, 'Mountain Time (US & Canada)'), -(7, -6.0, 'Central Time (US & Canada), Mexico City'), -(8, -5.0, 'Eastern Time (US & Canada), Bogota, Lima'), -(9, -4.0, 'Atlantic Time (Canada), Caracas, La Paz'), -(10, -3.5, 'Newfoundland'), -(11, -3.0, 'Brazil, Buenos Aires, Georgetown'), -(12, -2.0, 'Mid-Atlantic'), -(13, -1.0, 'Azores, Cape Verde Islands'), -(14, 0.0, 'Western Europe Time, London, Lisbon, Casablanca'), -(15, 1.0, 'Brussels, Copenhagen, Madrid, Paris'), -(16, 2.0, 'Kaliningrad, South Africa'), -(17, 3.0, 'Baghdad, Riyadh, Moscow, St. Petersburg'), -(18, 3.5, 'Tehran'), -(19, 4.0, 'Abu Dhabi, Muscat, Baku, Tbilisi'), -(20, 4.5, 'Kabul'), -(21, 5.0, 'Ekaterinburg, Islamabad, Karachi, Tashkent'), -(22, 5.5, 'Bombay, Calcutta, Madras, New Delhi'), -(23, 6.0, 'Almaty, Dhaka, Colombo'), -(24, 7.0, 'Bangkok, Hanoi, Jakarta'), -(25, 8.0, 'Beijing, Perth, Singapore, Hong Kong'), -(26, 9.0, 'Tokyo, Seoul, Osaka, Sapporo, Yakutsk'), -(27, 9.5, 'Adelaide, Darwin'), -(28, 10.0, 'Eastern Australia, Guam, Vladivostok'), -(29, 11.0, 'Magadan, Solomon Islands, New Caledonia'), -(30, 12.0, 'Auckland, Wellington, Fiji, Kamchatka'); diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql index 8d27e2076d8a726e2daa371fc4b47b7d88600a18..8faf7ac5c8ac6144c53cb58eec674aea6564db2c 100644 --- a/setup/inc/streams/core/install-mysql.sql +++ b/setup/inc/streams/core/install-mysql.sql @@ -173,6 +173,7 @@ INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES DROP TABLE IF EXISTS `%TABLE_PREFIX%form`; CREATE TABLE `%TABLE_PREFIX%form` ( `id` int(11) unsigned NOT NULL auto_increment, + `type` char(1) NOT NULL DEFAULT 'T', `title` varchar(255) NOT NULL, `instructions` varchar(512), `notes` text, @@ -203,7 +204,7 @@ CREATE TABLE `%TABLE_PREFIX%form_entry` ( `id` int(11) unsigned NOT NULL auto_increment, `form_id` int(11) unsigned NOT NULL, `object_id` int(11) unsigned, - `object_type` char(1), + `object_type` char(1) NOT NULL DEFAULT 'T', `sort` int(11) unsigned NOT NULL DEFAULT 1, `created` datetime NOT NULL, `updated` datetime NOT NULL, @@ -579,6 +580,8 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket`; CREATE TABLE `%TABLE_PREFIX%ticket` ( `ticket_id` int(11) unsigned NOT NULL auto_increment, `ticketID` int(11) unsigned NOT NULL default '0', + `user_id` int(11) unsigned NOT NULL default '0', + `user_email_id` int(11) unsigned NOT NULL default '0', `dept_id` int(10) unsigned NOT NULL default '0', `sla_id` int(10) unsigned NOT NULL default '0', `priority_id` int(10) unsigned NOT NULL default '0', @@ -748,3 +751,23 @@ CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%page` ( PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `%TABLE_PREFIX%user`; +CREATE TABLE `%TABLE_PREFIX%user` ( + `id` int(10) unsigned NOT NULL auto_increment, + `default_email_id` int(10) NOT NULL, + `first` varchar(64) NOT NULL, + `last` varchar(64), + `created` datetime NOT NULL, + `updated` datetime NOT NULL, + PRIMARY KEY (`id`) +); + +DROP TABLE IF EXISTS `%TABLE_PREFIX%user_email`; +CREATE TABLE `%TABLE_PREFIX%user_email` ( + `id` int(10) unsigned NOT NULL auto_increment, + `user_id` int(10) unsigned NOT NULL, + `address` varchar(128) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `address` (`address`) +);