From 6b762ab6e8e9ff6fb7c2eefc616f712ba74169c1 Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Wed, 11 Mar 2015 13:08:07 -0500 Subject: [PATCH] forms: Fix a couple places where validation errors are not propagated Reset field content when building a new form --- include/ajax.tickets.php | 2 +- include/class.dynamic_forms.php | 71 ++++++++++++++++++++++--------- include/class.filter.php | 16 ++++++- include/class.forms.php | 2 +- include/class.ticket.php | 2 +- include/class.user.php | 12 +++--- include/client/open.inc.php | 6 ++- include/staff/ticket-open.inc.php | 5 ++- tickets.php | 2 + 9 files changed, 82 insertions(+), 36 deletions(-) diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 4ad0d061f..21e93290c 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -575,7 +575,7 @@ class TicketsAjaxAPI extends AjaxController { Http::response(404, 'No such ticket/user'); $errors = array(); - if($user->updateInfo($_POST, $errors)) + if($user->updateInfo($_POST, $errors, true)) Http::response(201, $user->to_json()); $forms = $user->getForms(); diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 3d73b862d..fbdb14229 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -47,18 +47,17 @@ class DynamicForm extends VerySimpleModel { var $_dfields; function getFields($cache=true) { - if (!$cache) - $fields = false; - else - $fields = &$this->_fields; + if (!$cache) { + $this->_fields = null; + } - if (!$fields) { - $fields = new ListObject(); + if (!$this->_fields) { + $this->_fields = new ListObject(); foreach ($this->getDynamicFields() as $f) - $fields->append($f->getImpl($f)); + $this->_fields->append($f->getImpl($f)); } - return $fields; + return $this->_fields; } function getDynamicFields() { @@ -99,13 +98,39 @@ class DynamicForm extends VerySimpleModel { function getTitle() { return $this->get('title'); } function getInstructions() { return $this->get('instructions'); } + /** + * Drop field errors clean info etc. Useful when replacing the source + * content of the form. This is necessary because the field listing is + * cached under some circumstances. + */ + function reset() { + foreach ($this->getFields() as $f) + $f->reset(); + return $this; + } + function getForm($source=false) { - if (!$this->_form || $source) { - $fields = $this->getFields($this->_has_data); - $this->_form = new Form($fields, $source, array( - 'title'=>$this->title, 'instructions'=>$this->instructions)); + if ($source) + $this->reset(); + $fields = $this->getFields(); + $form = new Form($fields, $source, array( + 'title'=>$this->title, 'instructions'=>$this->instructions)); + return $form; + } + + function addErrors(array $formErrors, $replace=false) { + $fields = array(); + foreach ($this->getFields() as $f) + $fields[$f->get('id')] = $f; + foreach ($formErrors as $id => $fieldErrors) { + if (isset($fields[$id])) { + if ($replace) + $fields[$id]->_errors = $fieldErrors; + else + foreach ($fieldErrors as $E) + $fields[$id]->addError($E); + } } - return $this->_form; } function isDeletable() { @@ -324,8 +349,7 @@ class TicketForm extends DynamicForm { return; $f = $answer->getField(); - $name = $f->get('name') ? $f->get('name') - : 'field_'.$f->get('id'); + $name = $f->get('name') ?: ('field_'.$f->get('id')); $fields = sprintf('`%s`=', $name) . db_input( implode(',', $answer->getSearchKeys())); $sql = 'INSERT INTO `'.TABLE_PREFIX.'ticket__cdata` SET '.$fields @@ -695,12 +719,14 @@ class DynamicFormEntry extends VerySimpleModel { function getInstructions() { return $this->getForm()->getInstructions(); } function getForm() { - if (!isset($this->_form)) { - $this->_form = DynamicForm::lookup($this->get('form_id')); - if ($this->_form && isset($this->id)) - $this->_form->data($this); + $form = DynamicForm::lookup($this->get('form_id')); + if ($form) { + if (isset($this->id)) + $form->data($this); + if ($this->errors()) + $form->addErrors($this->errors(), true); } - return $this->_form; + return $form; } function getFields() { @@ -710,7 +736,10 @@ class DynamicFormEntry extends VerySimpleModel { // even when stored elsewhere -- important during validation foreach ($this->getForm()->getDynamicFields() as $field) { $field->setForm($this); - $this->_fields[$field->get('id')] = $field->getImpl($field); + $field = $field->getImpl($field); + if ($field instanceof ThreadEntryField) + continue; + $this->_fields[$field->get('id')] = $field; } // Get answers to entries foreach ($this->getAnswers() as $a) { diff --git a/include/class.filter.php b/include/class.filter.php index acc3a3590..b05a448ce 100644 --- a/include/class.filter.php +++ b/include/class.filter.php @@ -322,7 +322,8 @@ class Filter { if ($info['reply-to-name']) $ticket['name'] = $info['reply-to-name']; if ($changed) - throw new FilterDataChanged(); + throw new FilterDataChanged($ticket); + } # Use canned response. @@ -961,7 +962,18 @@ class RejectedException extends Exception { } } -class FilterDataChanged extends Exception {} +class FilterDataChanged extends Exception { + var $data; + + function __construct($data) { + parent::__construct('Ticket filter data changed'); + $this->data = $data; + } + + function getData() { + return $this->data; + } +} /** * Function: endsWith diff --git a/include/class.forms.php b/include/class.forms.php index 70c0510a6..7078692a0 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -30,7 +30,7 @@ class Form { $this->fields = $fields; foreach ($fields as $k=>$f) { $f->setForm($this); - if (!$f->get('name') && $k) + if (!$f->get('name') && $k && !is_numeric($k)) $f->set('name', $k); } if (isset($options['title'])) diff --git a/include/class.ticket.php b/include/class.ticket.php index 2619c625b..e7546870e 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -2378,7 +2378,7 @@ class Ticket { } catch (FilterDataChanged $ex) { // Don't pass user recursively, assume the user has changed - return self::filterTicketData($origin, $vars, $forms); + return self::filterTicketData($origin, $ex->getData(), $forms); } return $vars; } diff --git a/include/class.user.php b/include/class.user.php index 99375d65a..87edb06dd 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -342,7 +342,7 @@ class User extends UserModel { } } - $this->_forms[] = $cd->getForm(); + $this->_forms[] = $cd; } } @@ -497,15 +497,15 @@ class User extends UserModel { function updateInfo($vars, &$errors, $staff=false) { $valid = true; - $forms = $this->getDynamicData(); + $forms = $this->getForms($vars); foreach ($forms as $cd) { $cd->setSource($vars); if ($staff && !$cd->isValidForStaff()) $valid = false; - elseif (!$cd->isValidForClient()) + elseif (!$staff && !$cd->isValidForClient()) $valid = false; - elseif ($cd->get('type') == 'U' - && ($form= $cd->getForm()) + elseif (($form= $cd->getForm()) + && $form->get('type') == 'U' && ($f=$form->getField('email')) && $f->getClean() && ($u=User::lookup(array('emails__address'=>$f->getClean()))) @@ -518,7 +518,7 @@ class User extends UserModel { if (!$valid) return false; - foreach ($this->getDynamicData() as $cd) { + foreach ($forms as $cd) { if (($f=$cd->getForm()) && $f->get('type') == 'U') { if (($name = $f->getField('name'))) { $this->name = $name->getClean(); diff --git a/include/client/open.inc.php b/include/client/open.inc.php index 821aa6ef9..4024579a8 100644 --- a/include/client/open.inc.php +++ b/include/client/open.inc.php @@ -77,8 +77,10 @@ if ($info['topicId'] && ($topic=Topic::lookup($info['topicId']))) { } ?> </tbody> <tbody><?php - $tform = TicketForm::getInstance()->getForm($_POST); - if ($_POST) $tform->isValid(); + $tform = TicketForm::getInstance(); + if ($_POST) { + $tform->isValidForClient(); + } $tform->render(false); ?> </tbody> <tbody> diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index 39acb0864..6041f5573 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -265,8 +265,9 @@ if ($_POST) ?> </tbody> <tbody> <?php - $tform = TicketForm::getInstance()->getForm($_POST); - if ($_POST) $tform->isValid(); + $tform = TicketForm::getInstance(); + if ($_POST && !$tform->errors()) + $tform->isValidForStaff(); $tform->render(true); ?> </tbody> diff --git a/tickets.php b/tickets.php index 5b15b0015..fdafd5709 100644 --- a/tickets.php +++ b/tickets.php @@ -123,6 +123,8 @@ if($ticket && $ticket->checkUserAccess($thisclient)) { } include(CLIENTINC_DIR.'header.inc.php'); include(CLIENTINC_DIR.$inc); +if ($tform instanceof DynamicFormEntry) + $tform = $tform->getForm(); print $tform->getMedia(); include(CLIENTINC_DIR.'footer.inc.php'); ?> -- GitLab