diff --git a/include/class.company.php b/include/class.company.php index 049ecbb215a0abcbe1d6d25b0d5842c26fd97850..c9aa22f04af3889ea22b564f06ffdf2dff936a71 100644 --- a/include/class.company.php +++ b/include/class.company.php @@ -48,7 +48,7 @@ class Company { } function getInfo() { - return $this->getForm()->getSaved(); + return $this->getForm()->getClean(); } function getName() { diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 23829e8a471b3b63b72cb9c071ed763888e7c187..36dfce384166d14798fd6ce5462cab2bc63cda16 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -51,34 +51,37 @@ class DynamicForm extends VerySimpleModel { var $_has_data = false; var $_dfields; - function getFields($cache=true) { - if (!$cache) { - $this->_fields = null; - } + function getInfo() { + $base = $this->ht; + unset($base['fields']); + return $base; + } + /** + * Fetch a list of field implementations for the fields defined in this + * form. This method should *always* be preferred over + * ::getDynamicFields() to avoid caching confusion + */ + function getFields() { if (!$this->_fields) { $this->_fields = new ListObject(); foreach ($this->getDynamicFields() as $f) $this->_fields->append($f->getImpl($f)); } - return $this->_fields; } + /** + * Fetch the dynamic fields associated with this dynamic form. Do not + * use this list for data processing or validation. Use ::getFields() + * for that. + */ function getDynamicFields() { - if (!isset($this->id)) - return array(); - elseif (!$this->_dfields) { - $this->_dfields = DynamicFormField::objects() - ->filter(array('form_id'=>$this->id)) - ->all(); - foreach ($this->_dfields as $f) - $f->setForm($this); - } - return $this->_dfields; + return $this->fields; } - // Multiple inheritance -- delegate to Form + // Multiple inheritance -- delegate methods not defined to a forms API + // Form function __call($what, $args) { $delegate = array($this->getForm(), $what); if (!is_callable($delegate)) @@ -86,23 +89,14 @@ class DynamicForm extends VerySimpleModel { return call_user_func_array($delegate, $args); } - function getField($name, $cache=true) { - foreach ($this->getFields($cache) as $f) { - if (!strcasecmp($f->get('name'), $name)) - return $f; - } - if ($cache) - return $this->getField($name, false); + function getTitle() { + return $this->getLocal('title'); } - function hasField($name) { - return ($this->getField($name)); + function getInstructions() { + return $this->getLocal('instructions'); } - - function getTitle() { return $this->getLocal('title'); } - function getInstructions() { return $this->getLocal('instructions'); } - /** * Drop field errors clean info etc. Useful when replacing the source * content of the form. This is necessary because the field listing is @@ -119,37 +113,16 @@ class DynamicForm extends VerySimpleModel { $this->reset(); $fields = $this->getFields(); $form = new Form($fields, $source, array( - 'title'=>$this->getLocal('title'), 'instructions'=>$this->getLocal('instructions'))); + 'title' => $this->getLocal('title'), + 'instructions' => $this->getLocal('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); - } - } - } - function isDeletable() { return $this->get('deletable'); } - function disableFields(array $ids) { - foreach ($this->getFields() as $F) { - if (in_array($F->get('id'), $ids)) { - $F->disable(); - } - } - } - function hasAnyVisibleFields($user=false) { global $thisstaff, $thisclient; $user = $user ?: $thisstaff ?: $thisclient; @@ -167,16 +140,12 @@ class DynamicForm extends VerySimpleModel { return $visible > 0; } - function instanciate($sort=1) { - return DynamicFormEntry::create(array( + function instanciate($sort=1, $data=false) { + $entry = DynamicFormEntry::create(array( 'form_id'=>$this->get('id'), 'sort'=>$sort)); - } - - function data($data) { - if ($data instanceof DynamicFormEntry) { - $this->_fields = $data->getFields(); - $this->_has_data = true; - } + if ($data) + $entry->setSource($data); + return $entry; } function getTranslateTag($subtag) { @@ -205,33 +174,29 @@ class DynamicForm extends VerySimpleModel { return parent::delete(); } - function getExportableFields($exclude=array()) { - $fields = array(); foreach ($this->getFields() as $f) { // Ignore core fields if ($exclude && in_array($f->get('name'), $exclude)) continue; // Ignore non-data fields + // FIXME: Consider ::isStorable() too elseif (!$f->hasData() || $f->isPresentationOnly()) continue; $fields['__field_'.$f->get('id')] = $f; } - return $fields; } - static function create($ht=false) { $inst = parent::create($ht); $inst->set('created', new SqlFunction('NOW')); if (isset($ht['fields'])) { $inst->save(); foreach ($ht['fields'] as $f) { - $f = DynamicFormField::create($f); - $f->form_id = $inst->id; + $f = DynamicFormField::create(array('form' => $inst)); $f->setForm($inst); $f->save(); } @@ -427,7 +392,7 @@ class TicketForm extends DynamicForm { static function updateDynamicDataView($answer, $data) { // TODO: Detect $data['dirty'] for value and value_id // We're chiefly concerned with Ticket form answers - if (!($e = $answer->getEntry()) || $e->getForm()->get('type') != 'T') + if (!($e = $answer->getEntry()) || $e->form->get('type') != 'T') return; // $record = array(); @@ -477,11 +442,11 @@ Signal::connect('model.updated', Signal::connect('model.created', array('TicketForm', 'dropDynamicDataView'), 'DynamicFormField', - function($o) { return $o->getForm()->get('type') == 'T'; }); + function($o) { return $o->form->type == 'T'; }); Signal::connect('model.deleted', array('TicketForm', 'dropDynamicDataView'), 'DynamicFormField', - function($o) { return $o->getForm()->get('type') == 'T'; }); + function($o) { return $o->form->type == 'T'; }); // If the `name` column is in the dirty list, we would be renaming a // column. Delete the view instead. Signal::connect('model.updated', @@ -556,13 +521,18 @@ class DynamicFormField extends VerySimpleModel { const MASK_AGENT_FULL = 0x7000; - // Multiple inheritance -- delegate to FormField + // Multiple inheritance -- delegate methods not defined here to the + // forms API FormField instance function __call($what, $args) { return call_user_func_array( array($this->getField(), $what), $args); } - function getField($cache=true) { + /** + * Fetch a forms API FormField instance which represents this designable + * DynamicFormField. + */ + function getField() { global $thisstaff; // Finagle the `required` flag for the FormField instance @@ -570,16 +540,11 @@ class DynamicFormField extends VerySimpleModel { $ht['required'] = ($thisstaff) ? $this->isRequiredForStaff() : $this->isRequiredForUsers(); - if (!$cache) - return new FormField($ht); - if (!isset($this->_field)) $this->_field = new FormField($ht); return $this->_field; } - function getAnswer() { return $this->answer; } - /** * setConfiguration * @@ -642,6 +607,10 @@ class DynamicFormField extends VerySimpleModel { return (isset($this->flags) && ($this->flags & $flag) != 0); } + /** + * Describes the current visibility settings for this field. Returns a + * comma-separated, localized list of flag descriptions. + */ function getVisibilityDescription() { $F = $this->flags; @@ -683,6 +652,16 @@ class DynamicFormField extends VerySimpleModel { return $T != $tag ? $T : ($default ?: $this->get($subtag)); } + /** + * Fetch a list of names to flag settings to make configuring new fields + * a bit easier. + * + * Returns: + * <Array['desc', 'flags']>, where the 'desc' key is a localized + * description of the flag set, and the 'flags' key is a bit mask of + * flags which should be set on the new field to implement the + * requirement / visibility mode. + */ function allRequirementModes() { return array( 'a' => array('desc' => __('Optional'), @@ -711,6 +690,19 @@ class DynamicFormField extends VerySimpleModel { ); } + /** + * Fetch a list of valid requirement modes for this field. This list + * will be filtered based on flags which are not supported or not + * allowed for this field. + * + * Deprecated: + * This was used in previous versions when a drop-down list was + * presented for editing a field's visibility. The current software + * version presents the drop-down list for new fields only. + * + * Returns: + * <Array['desc', 'flags']> Filtered list from ::allRequirementModes + */ function getAllRequirementModes() { $modes = static::allRequirementModes(); if ($this->isPrivacyForced()) { @@ -844,7 +836,6 @@ class DynamicFormEntry extends VerySimpleModel { ), ); - var $_values; var $_fields; var $_form; var $_errors = false; @@ -856,14 +847,7 @@ class DynamicFormEntry extends VerySimpleModel { } function getAnswers() { - if (!isset($this->_values)) { - $this->_values = DynamicFormEntryAnswer::objects() - ->filter(array('entry_id'=>$this->get('id'))) - ->all(); - foreach ($this->_values as $v) - $v->entry = $this; - } - return $this->_values; + return $this->answers; } function getAnswer($name) { @@ -890,44 +874,69 @@ class DynamicFormEntry extends VerySimpleModel { return $this->_errors; } - function getTitle() { return $this->getForm()->getTitle(); } - function getInstructions() { return $this->getForm()->getInstructions(); } + function getTitle() { + return $this->form->getTitle(); + } + + function getInstructions() { + return $this->form->getInstructions(); + } + + function getDynamicForm() { + return $this->form; + } function getForm() { - $form = DynamicForm::lookup($this->get('form_id')); - if ($form) { - if (isset($this->id)) - $form->data($this); + if (!isset($this->_form)) { + // XXX: Should source be $this? + $form = new Form($this->getFields(), $this->getSource(), + array( + 'title' => $this->getTitle(), + 'instructions' => $this->getInstructions(), + )); if (isset($this->extra)) { $x = JsonDataParser::decode($this->extra) ?: array(); $form->disableFields($x['disable'] ?: array()); } - if ($this->errors()) - $form->addErrors($this->errors(), true); + $this->_form = $form; } - return $form; + return $this->_form; + } + + function getDynamicFields() { + return $this->form->fields; + } + + function getMedia() { + return $this->getForm()->getMedia(); } function getFields() { if (!isset($this->_fields)) { $this->_fields = array(); // Get all dynamic fields associated with the form - // even when stored elsewhere -- important during validation - foreach ($this->getForm()->getDynamicFields() as $field) { - $field = $field->getImpl($field); - if ($field instanceof ThreadEntryField) + // even when stored elsewhere -- important during validation + foreach ($this->getDynamicFields() as $f) { + $f = $f->getImpl($f); + if ($f instanceof ThreadEntryField) continue; - $this->_fields[$field->get('id')] = $field; + $this->_fields[$f->get('id')] = $f; + $f->isnew = true; } - // Get answers to entries + // Include any other answers included in this entry, which may + // be for fields which have since been deleted foreach ($this->getAnswers() as $a) { - if (!($f = $a->getField())) continue; - $this->_fields[$f->get('id')] = $f; + $f = $a->getField(); + $id = $f->get('id'); + if (!isset($this->_fields[$id])) { + // This field is not currently on the associated form + $a->deleted = true; + } + $this->_fields[$id] = $f; + // This field has an answer, so it isn't new (to this entry) + $f->isnew = false; } } - foreach ($this->_fields as $F) - $F->setForm($this); - return $this->_fields; } @@ -939,7 +948,6 @@ class DynamicFormEntry extends VerySimpleModel { } function getField($name) { - foreach ($this->getFields() as $field) if (!strcasecmp($field->get('name'), $name)) return $field; @@ -981,13 +989,7 @@ class DynamicFormEntry extends VerySimpleModel { } function getClean() { - if (!$this->_clean) { - $this->_clean = array(); - foreach ($this->getFields() as $field) - $this->_clean[$field->get('id')] - = $this->_clean[$field->get('name')] = $field->getClean(); - } - return $this->_clean; + return $this->getForm()->getClean(); } /** @@ -1023,16 +1025,6 @@ class DynamicFormEntry extends VerySimpleModel { return $vars; } - function getSaved() { - $info = array(); - foreach ($this->getAnswers() as $a) { - $field = $a->getField(); - $info[$field->get('id')] - = $info[$field->get('name')] = $a->getValue(); - } - return $info; - } - function forTicket($ticket_id, $force=false) { static $entries = array(); if (!isset($entries[$ticket_id]) || $force) { @@ -1077,29 +1069,14 @@ class DynamicFormEntry extends VerySimpleModel { * entry. */ function addMissingFields() { - // Track deletions - foreach ($this->getAnswers() as $answer) - $answer->deleted = true; - - foreach ($this->getForm()->getDynamicFields() as $field) { - $found = false; - foreach ($this->getAnswers() as $answer) { - if ($answer->get('field_id') == $field->get('id')) { - $answer->deleted = false; $found = true; break; - } - } - if (!$found && ($fImpl = $field->getImpl($field)) - && $field->isEnabled() - && !$fImpl->isPresentationOnly()) { + foreach ($this->getFields() as $field) { + if ($field->isnew && $field->isEnabled() + && !$field->isPresentationOnly()) { $a = DynamicFormEntryAnswer::create( - array('field_id'=>$field->get('id'), 'entry_id'=>$this->id)); - $a->field = $field; - $a->entry = $this; - $a->deleted = false; + array('field_id'=>$field->get('id'), 'entry'=>$this)); + // Add to list of answers - $this->_values[] = $a; - $this->_fields[$field->get('id')] = $fImpl; - $this->_form = null; + $this->answers->add($a); // Omit fields without data and non-storable fields. if (!$field->hasData() || !$field->isStorable()) @@ -1121,48 +1098,55 @@ class DynamicFormEntry extends VerySimpleModel { function save($refetch=false) { if (count($this->dirty)) $this->set('updated', new SqlFunction('NOW')); + if (!parent::save($refetch || count($this->dirty))) return false; - foreach ($this->getFields() as $field) { - if (!($a = $field->getAnswer()) || !$field->isStorable()) - continue; + foreach ($this->getAnswers() as $a) { + $field = $a->getField(); - $a = $field->getAnswer(); + // Don't save answers for presentation-only fields or fields + // which are stored elsewhere + if (!$field->hasData() || !$field->isStorable() + || $field->isPresentationOnly() + ) { + continue; + } // Set the entry ID here so that $field->getClean() can use the // entry-id if necessary - $a->set('entry_id', $this->get('id')); + $a->entry = $this; $val = $field->to_database($field->getClean()); if (is_array($val)) { $a->set('value', $val[0]); $a->set('value_id', $val[1]); } - else + else { $a->set('value', $val); - // Don't save answers for presentation-only fields - if ($field->hasData() && !$field->isPresentationOnly()) - $a->save(); + } + $a->save(); } - $this->_values = null; } function delete() { + if (!parent::delete()) + return false; + foreach ($this->getAnswers() as $a) $a->delete(); - return parent::delete(); + + return true; } static function create($ht=false) { $inst = parent::create($ht); $inst->set('created', new SqlFunction('NOW')); - foreach ($inst->getForm()->getDynamicFields() as $f) { - if (!$f->hasData()) continue; + foreach ($inst->getDynamicFields() as $field) { + if (!$field->getImpl()->hasData()) + continue; $a = DynamicFormEntryAnswer::create( - array('field_id'=>$f->get('id'))); - $a->field = $f; + array('field'=>$field, 'entry'=>$inst)); $a->field->setAnswer($a); - $a->entry = $inst; - $inst->_values[] = $a; + $inst->answers->add($a); } return $inst; } @@ -1192,8 +1176,6 @@ class DynamicFormEntryAnswer extends VerySimpleModel { ); var $_field; - var $form; - var $entry; var $deleted = false; var $_value; @@ -1202,9 +1184,7 @@ class DynamicFormEntryAnswer extends VerySimpleModel { } function getForm() { - if (!$this->form) - $this->form = $this->getEntry()->getForm(); - return $this->form; + return $this->getEntry()->getForm(); } function getField() { diff --git a/include/class.forms.php b/include/class.forms.php index efa445efc3829969f2931cfec366ddd6532e28ed..00d9a1c126a4a4d237a76de0096e6785e887bb14 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -61,6 +61,10 @@ class Form { return $fields[$name]; } + function hasField($name) { + return $this->getField($name); + } + function getTitle() { return $this->title; } function getInstructions() { return $this->instructions; } function getSource() { return $this->_source; } @@ -104,6 +108,14 @@ class Form { return $this->_clean; } + function disableFields(array $ids) { + foreach ($this->getFields() as $F) { + if (in_array($F->get('id'), $ids)) { + $F->disable(); + } + } + } + function errors($formOnly=false) { return ($formOnly) ? $this->_errors['form'] : $this->_errors; } diff --git a/include/class.organization.php b/include/class.organization.php index b5fed6c32115a366971834803f7f4f231771cdfc..c5b8de4d1895198180ec3efd5f7915f98ecde79b 100644 --- a/include/class.organization.php +++ b/include/class.organization.php @@ -180,18 +180,18 @@ class Organization extends OrganizationModel { if (!isset($this->_forms)) { $this->_forms = array(); - foreach ($this->getDynamicData() as $cd) { - $cd->addMissingFields(); + foreach ($this->getDynamicData() as $entry) { + $entry->addMissingFields(); if(!$data - && ($form = $cd->getForm()) + && ($form = $entry->getDynamicForm()) && $form->get('type') == 'O' ) { - foreach ($cd->getFields() as $f) { + foreach ($entry->getFields() as $f) { if ($f->get('name') == 'name') $f->value = $this->getName(); } } - $this->_forms[] = $cd->getForm(); + $this->_forms[] = $entry; } } @@ -251,11 +251,11 @@ class Organization extends OrganizationModel { function getFilterData() { $vars = array(); foreach ($this->getDynamicData() as $entry) { - if ($entry->getForm()->get('type') != 'O') + if ($entry->getDynamicForm()->get('type') != 'O') continue; $vars += $entry->getFilterData(); // Add special `name` field - $f = $entry->getForm()->getField('name'); + $f = $entry->getField('name'); $vars['field.'.$f->get('id')] = $this->getName(); } return $vars; @@ -308,12 +308,11 @@ class Organization extends OrganizationModel { $valid = true; $forms = $this->getForms($vars); - foreach ($forms as $cd) { - if (!$cd->isValid()) + foreach ($forms as $entry) { + if (!$entry->isValid()) $valid = false; - if ($cd->get('type') == 'O' - && ($form= $cd->getForm($vars)) - && ($f=$form->getField('name')) + if ($entry->getDynamicForm()->get('type') == 'O' + && ($f = $entry->getField('name')) && $f->getClean() && ($o=Organization::lookup(array('name'=>$f->getClean()))) && $o->id != $this->getId()) { @@ -347,14 +346,14 @@ class Organization extends OrganizationModel { if (!$valid || $errors) return false; - foreach ($this->getDynamicData() as $cd) { - if (($f=$cd->getForm()) - && ($f->get('type') == 'O') - && ($name = $f->getField('name'))) { - $this->name = $name->getClean(); - $this->save(); - } - $cd->save(); + foreach ($this->getDynamicData() as $entry) { + if ($entry->getDynamicForm()->get('type') == 'O' + && ($name = $entry->getField('name')) + ) { + $this->name = $name->getClean(); + $this->save(); + } + $entry->save(); } // Set flags @@ -379,11 +378,6 @@ class Organization extends OrganizationModel { } } - // Send signal for search engine updating if not modifying the - // fields specific to the organization - if (count($this->dirty) === 0) - Signal::send('model.updated', $this); - return $this->save(); } diff --git a/include/class.orm.php b/include/class.orm.php index ce9c830fcd2d7b8a5dc8a0d3fca8f45f9e0a144b..43795a8e75d3788a6c35082d3d260889806e379b 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -383,6 +383,7 @@ class VerySimpleModel { // First, if any foreign properties of this object are connected to // another *new* object, then save those objects first and set the // local foreign key field values + static::_inspect(); foreach (static::$meta['joins'] as $prop => $j) { if (isset($this->ht[$prop]) && ($foreign = $this->ht[$prop]) diff --git a/include/class.user.php b/include/class.user.php index 08e2ce3b4503a80f657d66ecaac54ae5b7d14e53..195e0de47aaa66f73ac15c681a154fca366948eb 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -285,12 +285,12 @@ class User extends UserModel { return $this->created; } - function addForm($form, $sort=1) { - $form = $form->instanciate(); - $form->set('sort', $sort); - $form->set('object_type', 'U'); - $form->set('object_id', $this->getId()); - $form->save(); + function addForm($form, $sort=1, $data=false) { + $entry = $form->instanciate($sort, $data); + $entry->set('object_type', 'U'); + $entry->set('object_id', $this->getId()); + $entry->save(); + return $entry; } function getLanguage($flags=false) { @@ -328,14 +328,7 @@ class User extends UserModel { } function addDynamicData($data) { - $uf = UserForm::getNewInstance(); - $uf->setClientId($this->id); - foreach ($uf->getFields() as $f) - if (isset($data[$f->get('name')])) - $uf->setAnswer($f->get('name'), $data[$f->get('name')]); - $uf->save(); - - return $uf; + return $this->addForm(UserForm::objects()->one(), 1, $data); } function getDynamicData($create=true) { @@ -355,12 +348,12 @@ class User extends UserModel { function getFilterData() { $vars = array(); foreach ($this->getDynamicData() as $entry) { - if ($entry->getForm()->get('type') != 'U') + if ($entry->getDynamicForm()->get('type') != 'U') continue; $vars += $entry->getFilterData(); // Add in special `name` and `email` fields foreach (array('name', 'email') as $name) { - if ($f = $entry->getForm()->getField($name)) + if ($f = $entry->getField($name)) $vars['field.'.$f->get('id')] = $name == 'name' ? $this->getName() : $this->getEmail(); } @@ -372,12 +365,12 @@ class User extends UserModel { if (!isset($this->_forms)) { $this->_forms = array(); - foreach ($this->getDynamicData() as $cd) { - $cd->addMissingFields(); + foreach ($this->getDynamicData() as $entry) { + $entry->addMissingFields(); if(!$data - && ($form = $cd->getForm()) + && ($form = $entry->getDynamicForm()) && $form->get('type') == 'U' ) { - foreach ($cd->getFields() as $f) { + foreach ($entry->getFields() as $f) { if ($f->get('name') == 'name') $f->value = $this->getFullName(); elseif ($f->get('name') == 'email') @@ -385,7 +378,7 @@ class User extends UserModel { } } - $this->_forms[] = $cd; + $this->_forms[] = $entry; } } @@ -549,13 +542,13 @@ class User extends UserModel { $valid = true; $forms = $this->getForms($vars); - foreach ($forms as $cd) { - $cd->setSource($vars); - if ($staff && !$cd->isValidForStaff()) + foreach ($forms as $entry) { + $entry->setSource($vars); + if ($staff && !$entry->isValidForStaff()) $valid = false; - elseif (!$staff && !$cd->isValidForClient()) + elseif (!$staff && !$entry->isValidForClient()) $valid = false; - elseif (($form= $cd->getForm()) + elseif (($form= $entry->getDynamicForm()) && $form->get('type') == 'U' && ($f=$form->getField('email')) && $f->getClean() @@ -569,8 +562,8 @@ class User extends UserModel { if (!$valid) return false; - foreach ($forms as $cd) { - if (($f=$cd->getForm()) && $f->get('type') == 'U') { + foreach ($forms as $entry) { + if (($f=$entry->getDynamicForm()) && $f->get('type') == 'U') { if (($name = $f->getField('name'))) { $this->name = $name->getClean(); $this->save(); @@ -581,7 +574,7 @@ class User extends UserModel { $this->default_email->save(); } } - $cd->save(); + $entry->save(); } return true; @@ -631,8 +624,8 @@ class User extends UserModel { $this->emails->expunge(); // Drop dynamic data - foreach ($this->getDynamicData() as $cd) { - $cd->delete(); + foreach ($this->getDynamicData() as $entry) { + $entry->delete(); } // Delete user diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php index a25f8ef27318aa3e7fc9f227986c4908880120c9..e194d4d8561b4d0a35fb365a85e8c7ca356ca6d3 100644 --- a/include/staff/dynamic-form.inc.php +++ b/include/staff/dynamic-form.inc.php @@ -6,7 +6,7 @@ if($form && $_REQUEST['a']!='add') { $action = 'update'; $url = "?id=".urlencode($_REQUEST['id']); $submit_text=__('Save Changes'); - $info = $form->ht; + $info = $form->getInfo(); $trans = array( 'title' => $form->getTranslateTag('title'), 'instructions' => $form->getTranslateTag('instructions'), diff --git a/include/staff/templates/dynamic-form.tmpl.php b/include/staff/templates/dynamic-form.tmpl.php index b6abadd3a6aeedf0616a8d2e04ef504f8a57f7da..7fac7eb1209eb21ad978e27c937c02c24d165e1f 100644 --- a/include/staff/templates/dynamic-form.tmpl.php +++ b/include/staff/templates/dynamic-form.tmpl.php @@ -24,7 +24,7 @@ if (isset($options['entry']) && $options['mode'] == 'edit') { ?> <?php if ($options['mode'] == 'edit') { ?> <div class="pull-right"> <?php if ($options['entry'] - && $options['entry']->getForm()->get('type') == 'G') { ?> + && $options['entry']->getDynamicForm()->get('type') == 'G') { ?> <a href="#" title="Delete Entry" onclick="javascript: $(this).closest('tbody').remove(); return false;"><i class="icon-trash"></i></a> diff --git a/include/staff/templates/form-manage.tmpl.php b/include/staff/templates/form-manage.tmpl.php index 05b15e89e91dc3a0c32f7b1549c12cd5fb5136fd..e002ef1654dc3273938aed81383ac5fe2ad4be20 100644 --- a/include/staff/templates/form-manage.tmpl.php +++ b/include/staff/templates/form-manage.tmpl.php @@ -12,9 +12,9 @@ $current_list = array(); foreach ($forms as $e) { ?> <div class="sortable row-item" data-id="<?php echo $e->get('id'); ?>"> <input type="hidden" name="forms[]" value="<?php echo $e->get('form_id'); ?>" /> - <i class="icon-reorder"></i> <?php echo $e->getForm()->getTitle(); + <i class="icon-reorder"></i> <?php echo $e->getTitle(); $current_list[] = $e->get('form_id'); - if ($e->getForm()->get('type') == 'G') { ?> + if ($e->getDynamicForm()->get('type') == 'G') { ?> <div class="button-group"> <div class="delete"><a href="#"><i class="icon-trash"></i></a></div> </div> diff --git a/include/staff/templates/org.tmpl.php b/include/staff/templates/org.tmpl.php index 561cba8f678fe5b77efbcc53ddfc070059fe9c5f..41fcec1ee8d99b60b51446b7ea83e1216e10e16d 100644 --- a/include/staff/templates/org.tmpl.php +++ b/include/staff/templates/org.tmpl.php @@ -28,7 +28,7 @@ if ($info['error']) { <?php foreach ($org->getDynamicData() as $entry) { ?> <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php - echo $entry->getForm()->get('title'); ?></strong></td></tr> + echo $entry->getTitle(); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> diff --git a/include/staff/templates/user-delete.tmpl.php b/include/staff/templates/user-delete.tmpl.php index b563643d284146896f33ce2df58532d6da5d4554..35bb685be93e07e0ca69efded5f0fe6c3466ff43 100644 --- a/include/staff/templates/user-delete.tmpl.php +++ b/include/staff/templates/user-delete.tmpl.php @@ -35,7 +35,7 @@ if ($info['error']) { <?php foreach ($user->getDynamicData() as $entry) { ?> <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php - echo $entry->getForm()->get('title'); ?></strong></td></tr> + echo $entry->getTitle(); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php index 568df91f8d84ed4c4cb18fcf2745722e2e613a13..948026e8ff188f4ce6fb7ee5c1319db346226314 100644 --- a/include/staff/templates/user-lookup.tmpl.php +++ b/include/staff/templates/user-lookup.tmpl.php @@ -44,7 +44,7 @@ if ($user) { ?> <table style="margin-top: 1em;"> <?php foreach ($user->getDynamicData() as $entry) { ?> <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php - echo $entry->getForm()->get('title'); ?></strong></td></tr> + echo $entry->getTitle(); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php index 55538502017858db5a38abd5bf04f69e395cc620..8c89749991d6bec12ebf2f901dacc57893ee324a 100644 --- a/include/staff/templates/user.tmpl.php +++ b/include/staff/templates/user.tmpl.php @@ -62,7 +62,7 @@ if ($info['error']) { <?php foreach ($user->getDynamicData() as $entry) { ?> <tr><th colspan="2"><strong><?php - echo $entry->getForm()->get('title'); ?></strong></td></tr> + echo $entry->getTitle(); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> <tr><td style="width:30%;"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> @@ -86,7 +86,7 @@ if ($info['error']) { <?php foreach ($org->getDynamicData() as $entry) { ?> <tr><th colspan="2"><strong><?php - echo $entry->getForm()->get('title'); ?></strong></td></tr> + echo $entry->getTitle(); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> <tr><td style="width:30%"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index 55241ed1859dcef7290eff40b96d5f613142178e..a054b841b6f71eced09e27e52eb00161ed6d71a0 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -350,10 +350,10 @@ foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) { // TODO: Rewrite getAnswers() so that one could write // ->getAnswers()->filter(not(array('field__name__in'=> // array('email', ...)))); - $answers = array_filter($form->getAnswers(), function ($a) { - return !in_array($a->getField()->get('name'), - array('email','subject','name','priority')); - }); + $answers = $form->getAnswers()->exclude(Q::any(array( + 'field__flags__hasbit' => DynamicFormField::FLAG_EXT_STORED, + 'field__name__in' => array('subject', 'priority') + ))); if (count($answers) == 0) continue; ?> diff --git a/include/upgrader/streams/core/b26f29a6-1ee831c8.patch.sql b/include/upgrader/streams/core/b26f29a6-1ee831c8.patch.sql index bb7f38eda3af26467600ac09768539b0a891bd71..62621faf484b725007590480c62549ed8a60015b 100644 --- a/include/upgrader/streams/core/b26f29a6-1ee831c8.patch.sql +++ b/include/upgrader/streams/core/b26f29a6-1ee831c8.patch.sql @@ -185,6 +185,11 @@ UPDATE `%TABLE_PREFIX%form_field` A1 JOIN `%TABLE_PREFIX%form` A2 ON(A2.id=A1.fo SET A1.`flags`=3 WHERE A2.`type`='O' AND A1.`name` IN('name'); +-- Thread entry field is stored externally +UPDATE `%TABLE_PREFIX%form_field` A1 JOIN `%TABLE_PREFIX%form` A2 ON(A2.id=A1.form_id) + SET A1.`flags`=3 + WHERE A2.`type`='T' AND A1.`name` IN ('message'); + -- Coalesce to zero here in case the config option has never been saved set @client_edit = coalesce( (select value from `%TABLE_PREFIX%config` where `key` = diff --git a/scp/forms.php b/scp/forms.php index 3b7e6af04e7f137af5732a6d7866fb169fd2a495..2e164f24385de0ff92431634de3a114a20409bd3 100644 --- a/scp/forms.php +++ b/scp/forms.php @@ -113,7 +113,7 @@ if($_POST) { 'name'=>trim($_POST["name-new-$i"]), )); $field->setRequirementMode($_POST["visibility-new-$i"]); - $field->setForm($form); + $form->fields->add($field); if (in_array($field->get('name'), $names)) $field->addError(__('Field variable name is not unique'), 'name'); if ($field->isValid()) { @@ -124,9 +124,7 @@ if($_POST) { else $errors["new-$i"] = $field->errors(); } - // XXX: Move to an instrumented list that can handle this better if (!$errors) { - $form->_dfields = $form->_fields = null; $form->save(true); foreach ($form_fields as $field) { $field->set('form_id', $form->get('id')); diff --git a/scp/lists.php b/scp/lists.php index 628e60b059e73c564c5e23f5e10b7fbf2c0eb1ed..89173a88e5b8eb455786bd77a6b1c6521f9e62a9 100644 --- a/scp/lists.php +++ b/scp/lists.php @@ -95,6 +95,7 @@ if($_POST) { break; case 'add': if ($list=DynamicList::add($_POST, $errors)) { + $form = $list->getForm(true); $msg = sprintf(__('Successfully added %s'), __('this custom list')); } elseif ($errors) { @@ -154,7 +155,6 @@ if($_POST) { if (!$_POST["prop-label-new-$i"]) continue; $field = DynamicFormField::create(array( - 'form_id' => $form->get('id'), 'sort' => $_POST["prop-sort-new-$i"] ?: ++$max_sort, 'label' => $_POST["prop-label-new-$i"], 'type' => $_POST["type-new-$i"], @@ -163,15 +163,13 @@ if($_POST) { | DynamicFormField::FLAG_AGENT_VIEW | DynamicFormField::FLAG_AGENT_EDIT, )); - $field->setForm($form); - if ($field->isValid()) + if ($field->isValid()) { + $form->fields->add($field); $field->save(); + } else $errors["new-$i"] = $field->errors(); } - // XXX: Move to an instrumented list that can handle this better - if (!$errors) - $form->_dfields = $form->_fields = null; } }