Hi all,
We often have quite a few of our custom fields in Tickets put into the Custom Field Groupings in the RT_SiteConfig
. One thing that has bugged me occasionally is that the CFs in a grouping are in an ordered array in the config, but the array ordering isn’t reflected when displaying the CFs. Instead the ordering is defined either per queue or by CF creation time. Last week I ended up spending an hour or so making a custom local overlay to fix this, which I thought I’d share here in case anyone was interested.
The “hack” comes in three parts: an overlay for lib/RT/CustomFields.pm
, a minor tweak needed in a local copy of /Elements/ShowCustomFields
and an extra config variable to turn this behaviour on. First off the overlay, which we’ve got in /opt/rt5/local/lib/RT/CustomFields_Local.pm
:
#!/usr/bin/perl
package RT::CustomFields;
use warnings;
use strict;
use Carp;
use Data::Dumper;
no warnings qw(redefine);
sub GroupingSort {
my $self = shift;
my $obj = shift;
my $grouping = shift;
my $grouping_class = $self->NewItem->_GroupingClass($obj);
my $config = RT->Config->Get('CustomFieldGroupings');
$config = {} unless ref($config) eq 'HASH';
$config = $config->{$grouping_class} || [];
my %h = ref $config eq "ARRAY" ? @{$config} : %{$config};
if ( $grouping ) {
my $list = $h{$grouping};
$self->{'__GroupingSort'} = $list;
$self->{'__GroupingSortPos'} = -1;
}
return;
}
sub NoGroupingSort {
my $self = shift;
$self->{'__GroupingSort'} = undef;
return;
}
sub Next {
my $self = shift;
if($self->{'__GroupingSort'}) {
$self->_DoSearch() if $self->{'must_redo_search'};
$self->{'__GroupingSortPos'}++;
my $CFName = $self->{'__GroupingSort'}[$self->{'__GroupingSortPos'}];
if(!$CFName) {
# Gone through the whole list, so back to the start
$self->{'__GroupingSortPos'} = -1;
return(undef);
} else {
foreach my $thisCF (@{$self->{'items'}}) {
if($thisCF->Name eq $CFName) {
return($thisCF);
}
}
return(undef);
}
} else {
return ( $self->SUPER::Next() );
}
}
sub Last {
my $self = shift;
if($self->{'__GroupingSort'}) {
my $CFName =
$self->{'__GroupingSort'}[scalar(@{$self->{'__GroupingSort'}})-1];
foreach my $thisCF (@{$self->{'items'}}) {
if($thisCF->Name eq $CFName) {
return($thisCF);
}
}
return(undef);
} else {
return ( $self->SUPER::Last() );
}
}
sub GotoFirstItem {
my $self = shift;
if($self->{'__GroupingSort'}) {
$self->{'__GroupingSortPos'} = -1;
} else {
return ( $self->SUPER::GotoFirstItem() );
}
}
1;
Then I made a local copy of /opt/rt5/share/html/Elements/ShowCustomFields
into /opt/rt5/local/html/Elements/ShowCustomFields
and applied this small diff:
$ diff ShowCustomFields /opt/rt5/share/html/Elements/ShowCustomFields
107,111d106
< # If this is in a grouping and we've asked for sorting based on CustomFieldGrouping arrays, turn that on now.
< if(defined $Grouping && RT->Config->Get('CustomFieldGroupingsSort') eq 'true') {
< $CustomFields->GroupingSort( $Object => $Grouping );
< }
<
Lastly in the RT_SiteConfig.pm
(or in our case a separate custom field groupings sub-config) we have an extra line:
Set($CustomFieldGroupingsSort, 'true');
Once these are in place, do the usual Mason cache flush/webserver kick dance and you should find that custom field groups are now shown sorted based on the order of the arrays in the %CustomFieldGroups
hash in the config. The win for us is that we’re doing a spot of preparatory work on a potential new system which will possibly be generating lots of queues dynamically, so by doing this we don’t have to fiddle with CF sort orders in each queue. Every queue gets its CF sort orders in groupings from the main config file and we can update/alter the array order in that config once for all queues. Hoorah!