Tuesday, October 20, 2009

Adding Custom Field Multi-Select to Bugzilla 3.4.2


I administrate a Bugzilla installation used by the software-development arm of our company to track their progress. I never touched it before being given the task of upgrading a 2.14 installation to 3.4.2.

The previous maintainer manually added fields to the database, which were carried forward but not compatible with the new Custom Fields fuctionality in the latest version of Bugzilla. All the data was still available if you manually entered a query for it but it wasn't available to show up anywhere, and the fields themselves were hidden.

In order to correct this issue, I created a new Custom Field and called it cf_target_milestone, established the legal values for the field and migrated the old data forward:

UPDATE bugs SET cf_target_milestone = target_milestone;

This populated the new column in the table with all the old data. Now, we have the data in place, we needed to add a way to search on it. A Bugzilla newsgroup posting has some steps towards that. I added a block just below the other multiselect fields in template/en/default/search/form.html.tmpl, around line 410:

[%################################################%]
[%# Block for Custom SELECT fields #%]
[%################################################%]

[% BLOCK cf_select %]
<td align="left">
<select name="[% sel.field_obj.name %]" id="[% sel.field_obj.name %]"
multiple="multiple" size="[% sel.size %]">
[% FOREACH name = sel.field_obj.legal_values %]
<option value="[% name FILTER html %]">
[% name FILTER html %]
</option>
[% END %]
</select>
</td> [% END %]
<hr>
[%# *** Custom Drop-down Fields *** %]
<table>
<tr>
[% USE Bugzilla %]
[% cf_fields = Bugzilla.get_fields({ obsolete => 0, custom => 1, type =>constants.FIELD_TYPE_SINGLE_SELECT }) %]
[% IF cf_fields %]
[% count = 0 %]
[% FOREACH field = cf_fields %]
[% count = count + 1 %]
<td>
<table>
<tr>
<th align="left">
<label for="[% field.name FILTER html %]" accesskey="a">
[%field_descs.${field.name} %]
</label>:
</th>
</tr>
<tr valign="top">
[% PROCESS cf_select sel = { field_obj => field, size => 7 } %]
</tr>
</table>
</td>
[% "</tr><tr>" IF (count % 5) == 0 %]
[% END %]
[% END %]
</tr>
</table>
I also added this code to query.cgi around line 145, below "my @custom_select_fields"

my @cf_fields = Bugzilla::get_fields({ custom => 1, obsolete => 0 });
foreach my $field (@cf_fields) {
$default{$field->name} = [];
}

These lines automatically pick up any custom fields you have: I only have one, but it will correctly work for multiples. Now, you have multi-select boxes but need to make one further change. field_obj.legal_values returns an object, not a string: in order to get the actual text out of it, we need to change both instances of name to name.name:

[% FOREACH name = sel.field_obj.legal_values %]
[% name.name FILTER html %]
[% END %]

Now we're set! Searching in custom drop-down fields is now enabled. I used Quick Escape, a nice web utility for escaping HTML entities, while making this post so I could display the template HTML.

No comments:

Post a Comment