From c7d7f4030abbafae1ed6ee71112b0e08eaf3a657 Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Wed, 30 Sep 2015 19:09:12 -0500 Subject: [PATCH] queue: Fix dropdowns for data-source and filter And add options for custom data form fields --- include/ajax.search.php | 6 +- include/class.dept.php | 4 ++ include/class.list.php | 4 ++ include/class.organization.php | 4 ++ include/class.queue.php | 63 +++++++++------- include/class.search.php | 71 ++++++++++++++++--- include/class.staff.php | 4 ++ include/class.ticket.php | 4 ++ include/class.topic.php | 4 ++ include/class.user.php | 4 ++ include/staff/queue.inc.php | 10 +-- .../templates/queue-column-condition.tmpl.php | 2 +- include/staff/templates/queue-column.tmpl.php | 3 +- 13 files changed, 140 insertions(+), 43 deletions(-) diff --git a/include/ajax.search.php b/include/ajax.search.php index be38dbf4a..d670d6caf 100644 --- a/include/ajax.search.php +++ b/include/ajax.search.php @@ -256,7 +256,7 @@ class SearchAjaxAPI extends AjaxController { Format::htmlchars($_GET['field'])); } - $field = $fields[$_GET['field']]; + list($label, $field) = $fields[$_GET['field']]; // Ensure `name` is preserved $field_name = $_GET['field']; $id = $_GET['id']; @@ -299,10 +299,10 @@ class SearchAjaxAPI extends AjaxController { } // Get the tabbed column configuration - $F = $fields[$field]; + list($label, $F) = $fields[$field]; $column = QueueColumn::create(array( "id" => (int) $_GET['id'], - "heading" => _S($F->getLabel()), + "heading" => _S($field->getLabel()), "primary" => $field, "width" => 100, )); diff --git a/include/class.dept.php b/include/class.dept.php index b54913af4..93e1b4673 100644 --- a/include/class.dept.php +++ b/include/class.dept.php @@ -110,6 +110,10 @@ implements TemplateVariable, Searchable { ); } + static function supportsCustomData() { + return false; + } + function getId() { return $this->id; } diff --git a/include/class.list.php b/include/class.list.php index 20bc6b87b..3cd9eec9e 100644 --- a/include/class.list.php +++ b/include/class.list.php @@ -1285,6 +1285,10 @@ implements CustomListItem, TemplateVariable, Searchable { ); } + static function supportsCustomData() { + return false; + } + function getList() { if (!isset($this->_list)) $this->_list = DynamicList::lookup(array('type' => 'ticket-status')); diff --git a/include/class.organization.php b/include/class.organization.php index db49618cb..2a9571367 100644 --- a/include/class.organization.php +++ b/include/class.organization.php @@ -356,6 +356,10 @@ implements TemplateVariable, Searchable { return $base; } + static function supportsCustomData() { + return true; + } + function update($vars, &$errors) { $valid = true; diff --git a/include/class.queue.php b/include/class.queue.php index e18749e29..d028eef95 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -185,7 +185,7 @@ class CustomQueue extends SavedSearch { function getQuickFilterField($value=null) { if ($this->filter && ($fields = SavedSearch::getSearchableFields($this->getRoot())) - && ($f = @$fields[$this->filter]) + && (list(,$f) = @$fields[$this->filter]) && $f->supportsQuickFilter() ) { $f->value = $value; @@ -407,7 +407,8 @@ extends ChoiceField { $root = $config['root']; $fields = array(); foreach (SavedSearch::getSearchableFields($root) as $path=>$f) { - $fields[$path] = $f->get('label'); + list($label,) = $f; + $fields[$path] = $label; } return $fields; } @@ -439,16 +440,20 @@ class QueueColumnCondition { )); } - function getField() { - // FIXME - #$root = $this->getColumn()->getQueue()->getRoot(); - $root = 'Ticket'; - $searchable = SavedSearch::getSearchableFields($root); - list($name, $method, $value) = $this->config['crit']; + function getField($name=null) { + // FIXME + #$root = $this->getColumn()->getQueue()->getRoot(); + $root = 'Ticket'; + $searchable = SavedSearch::getSearchableFields($root); + + if (!isset($name)) + list($name) = $this->config['crit']; - // Lookup the field to search this condition - if (isset($searchable[$name])) - return $searchable[$name]; + // Lookup the field to search this condition + if (isset($searchable[$name])) { + list(,$field) = $searchable[$name]; + return $field; + } } function getFieldName() { @@ -460,7 +465,7 @@ class QueueColumnCondition { list($name, $method, $value) = $this->config['crit']; // Fetch a criteria Q for the query - if ($field = $this->getField()) + if ($field = $this->getField($name)) return $field->getSearchQ($method, $value, $name); } @@ -478,7 +483,7 @@ class QueueColumnCondition { continue; // Lookup the field to search this condition - $field = $searchable[$name]; + list($label, $field) = $searchable[$name]; // Get the search method and value $method = $v; @@ -709,11 +714,18 @@ extends VerySimpleModel { // TODO: Consider data filter if configured - if (($F = $fields[$primary]) && ($T = $F->from_query($row, $primary))) - return $F->display($F->to_php($T)); - - if (($F = $fields[$secondary]) && ($T = $F->from_query($row, $secondary))) - return $F->display($F->to_php($T)); + if (($F = $fields[$primary]) + && (list(,$field) = $F) + && ($T = $field->from_query($row, $primary)) + ) { + return $field->display($field->to_php($T)); + } + if (($F = $fields[$secondary]) + && (list(,$field) = $F) + && ($T = $F->from_query($row, $secondary)) + ) { + return $field->display($field->to_php($T)); + } } function getTruncateClass() { @@ -731,13 +743,16 @@ extends VerySimpleModel { function mangleQuery($query) { // Basic data $fields = SavedSearch::getSearchableFields($this->getQueue()->getRoot()); - if ($primary = $fields[$this->primary]) - $query = $primary->addToQuery($query, + if ($primary = $fields[$this->primary]) { + list(,$field) = $primary; + $query = $field->addToQuery($query, $this->getOrmPath($this->primary)); - - if ($secondary = $fields[$this->secondary]) - $query = $secondary->addToQuery($query, + } + if ($secondary = $fields[$this->secondary]) { + list(,$field) = $secondary; + $query = $field->addToQuery($query, $this->getOrmPath($this->secondary)); + } switch ($this->link) { // XXX: Consider the ROOT of the related queue @@ -824,7 +839,7 @@ extends VerySimpleModel { if (!isset($fields[$name])) // No such field exists for this queue root type continue; - $field = $fields[$name]; + list(,$field) = $fields[$name]; $parts = SavedSearch::getSearchField($field, $name); $search_form = new SimpleForm($parts, $vars, array('id' => $id)); $search_form->getField("{$name}+search")->value = true; diff --git a/include/class.search.php b/include/class.search.php index 862567654..eea827a83 100644 --- a/include/class.search.php +++ b/include/class.search.php @@ -881,31 +881,78 @@ class SavedSearch extends VerySimpleModel { ); } - static function getSearchableFields($base, $recurse=2, $cache=true) { - static $cache; + /** + * Parameters: + * $base - Class, name of a class implementing Searchable + * $recurse - int, number of levels to recurse, default is 2 + * $cache - bool, cache results for future class for the same base + * $customData - bool, include all custom data fields for all general + * forms + */ + static function getSearchableFields($base, $recurse=2, $cache=true, + $customData=true + ) { + static $cache, $otherFields; if (!in_array('Searchable', class_implements($base))) return array(); - // FIXME: The fields from dynamicFormFields seem to be cached, and - // setting the label is preserved across multiple calls to this - // function. The caching helps with this phenomenon, but a better - // mechanism should be employed + // Early exit if already cached if ($cache && isset($cache[$base])) return $cache[$base]; - $fields = $base::getSearchableFields(); + $fields = array(); + foreach ($base::getSearchableFields() as $path=>$F) { + if (is_array($F)) { + list($label, $field) = $F; + } + else { + $label = $F->get('label'); + $field = $F; + } + $fields[$path] = array($label, $field); + } + if ($recurse) { foreach ($base::getMeta('joins') as $path=>$j) { $fc = $j['fkey'][0]; if ($fc == $base || $j['list'] || $j['reverse']) continue; - foreach (static::getSearchableFields($fc, $recurse-1, false) as $path2=>$F) { - $fields["{$path}__{$path2}"] = $F; - $F->set('label', sprintf("%s / %s", $fc, $F->get('label'))); + foreach (static::getSearchableFields($fc, $recurse-1, false) + as $path2=>$F) { + if (is_array($F)) { + list($label, $field) = $F; + } + else { + $label = $F->get('label'); + $field = $F; + } + $fields["{$path}__{$path2}"] = array( + sprintf("%s / %s", $fc, $label), + $field); } } } + + if ($customData && $base::supportsCustomData()) { + if (!isset($otherFields)) { + $otherFields = array(); + $forms = DynamicForm::objects()->filter(array('type'=>'G')); + foreach ($forms as $F) { + foreach ($F->getFields() as $field) { + $otherFields[$field->getId()] = array($F, $field); + } + } + } + foreach ($otherFields as $id=>$F) { + list($form, $field) = $F; + $label = sprintf("%s / %s", + $form->getTitle(), $field->get('label')); + $fields["entries__answers!{$id}__value"] = array( + $label, $field); + } + } + if ($cache) $cache[$base] = $fields; return $fields; @@ -1355,4 +1402,8 @@ interface Searchable { // used when this list is rendered in a dropdown, and the field search // mechanisms are use to apply query filtering based on the field. static function getSearchableFields(); + + // Determine if the object supports abritrary form additions, through + // the "Manage Forms" dialog usually + static function supportsCustomData(); } diff --git a/include/class.staff.php b/include/class.staff.php index ce922b1af..4f0784b52 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -135,6 +135,10 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable { ); } + static function supportsCustomData() { + return false; + } + function getHashtable() { $base = $this->ht; unset($base['teams']); diff --git a/include/class.ticket.php b/include/class.ticket.php index 0fc4f021d..773296f5a 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -1998,6 +1998,10 @@ implements RestrictedAccess, Threadable, Searchable { return $base; } + static function supportsCustomData() { + return true; + } + //Replace base variables. function replaceVars($input, $vars = array()) { global $ost; diff --git a/include/class.topic.php b/include/class.topic.php index ead2e57b6..c2506b421 100644 --- a/include/class.topic.php +++ b/include/class.topic.php @@ -99,6 +99,10 @@ implements TemplateVariable, Searchable { ); } + static function supportsCustomData() { + return false; + } + function getId() { return $this->topic_id; } diff --git a/include/class.user.php b/include/class.user.php index 7a5fe572a..22b996bc4 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -377,6 +377,10 @@ implements TemplateVariable, Searchable { return $base; } + static function supportsCustomData() { + return true; + } + function addDynamicData($data) { return $this->addForm(UserForm::objects()->one(), 1, $data); } diff --git a/include/staff/queue.inc.php b/include/staff/queue.inc.php index 8d4cdd509..bfe6b4476 100644 --- a/include/staff/queue.inc.php +++ b/include/staff/queue.inc.php @@ -88,12 +88,13 @@ else { <select name="filter"> <option value="::">— <?php echo __('Inherit from parent'); ?> —</option> <?php foreach (SavedSearch::getSearchableFields('Ticket') as $path=>$f) { - if (!$f->supportsQuickFilter()) + list($label, $field) = $f; + if (!$field->supportsQuickFilter()) continue; ?> <option value="<?php echo $path; ?>" <?php if ($path == $queue->filter) echo 'selected="selected"'; ?> - ><?php echo $f->get('label'); ?></option> + ><?php echo $label; ?></option> <?php } ?> </select> <br/> @@ -140,8 +141,9 @@ else { }); "> <option value="">— <?php echo __('Add a column'); ?> —</option> -<?php foreach (SavedSearch::getSearchableFields('Ticket') as $path=>$f) { ?> - <option value="<?php echo $path; ?>"><?php echo $f->get('label'); ?></option> +<?php foreach (SavedSearch::getSearchableFields('Ticket') as $path=>$f) { + list($label,) = $f; ?> + <option value="<?php echo $path; ?>"><?php echo $label; ?></option> <?php } ?> </select> diff --git a/include/staff/templates/queue-column-condition.tmpl.php b/include/staff/templates/queue-column-condition.tmpl.php index 659158d06..ea090ac36 100644 --- a/include/staff/templates/queue-column-condition.tmpl.php +++ b/include/staff/templates/queue-column-condition.tmpl.php @@ -16,7 +16,7 @@ <a href="#" onclick="javascript: $(this).closest('.condition').remove(); "><i class="icon-trash"></i></a> </div> - <?php echo $field->get('label'); ?> + <?php echo $label ?: $field->getLabel(); ?> <div class="advanced-search"> <?php $parts = SavedSearch::getSearchField($field, $field_name); diff --git a/include/staff/templates/queue-column.tmpl.php b/include/staff/templates/queue-column.tmpl.php index d8d9f6de7..65b251338 100644 --- a/include/staff/templates/queue-column.tmpl.php +++ b/include/staff/templates/queue-column.tmpl.php @@ -125,7 +125,8 @@ if ($column->getConditions()) { <option>— <?php echo __("Add a condition"); ?> —</option> <?php foreach (SavedSearch::getSearchableFields('Ticket') as $path=>$f) { - echo sprintf('<option value="%s">%s</option>', $path, Format::htmlchars($f->get('label'))); + list($label) = $f; + echo sprintf('<option value="%s">%s</option>', $path, Format::htmlchars($label)); } ?> </select> -- GitLab