[Rt-commit] rt branch, 4.6/priority-as-string, created. rt-4.4.2-97-g53affddf2

Michel Rodriguez michel at bestpractical.com
Wed Jun 12 08:45:06 EDT 2019


The branch, 4.6/priority-as-string has been created
        at  53affddf2d0deb03628c60a7b85ce923ece4c499 (commit)

- Log -----------------------------------------------------------------
commit e4dcd082eae31c954284613b4a1c166375c78525
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Feb 16 05:21:41 2018 +0800

    reapply dropped changes of "Remove dashboard from menu if it can't be loaded"
    
    original commit is bc441b84, it's been merged but the
    RemoveDashboardMenuItem call in /Elements/Tabs got dropped accidently
    later(probably when we merged another change to move related code to
    MenuBuilder.pm)

diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
index 604d00875..6a0e18306 100644
--- a/lib/RT/Interface/Web/MenuBuilder.pm
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -113,7 +113,13 @@ sub BuildMainNav {
         if ( $status ) {
             push @dashboards, $dash;
         } else {
-            $RT::Logger->warning( "Failed to load dashboard $id: $msg" );
+            $RT::Logger->debug( "Failed to load dashboard $id: $msg, removing from menu" );
+            $home->RemoveDashboardMenuItem(
+                DashboardId => $id,
+                CurrentUser => $HTML::Mason::Commands::session{CurrentUser}->UserObj,
+            );
+            @{ $HTML::Mason::Commands::session{'dashboards_in_menu'} } =
+              grep { $_ != $id } @{ $HTML::Mason::Commands::session{'dashboards_in_menu'} };
         }
     }
 

commit 52a22b45456c4fe371829cba487adea6919dfe04
Author: Brian C. Duggan <brian at bestpractical.com>
Date:   Tue May 29 19:08:30 2018 -0400

    Core RT::Extension::PriorityAsString
    existing behavior of extension.

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index fae0d46d4..169d5e22a 100644
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -149,8 +149,14 @@ Set( @StaticRoots, () );
 
 =back
 
+=head2 C<@ClearHash>
 
+Set this array for config values that should have the default hash keys completly removed in
+favor or new ones set in config.
 
+=cut
+
+Set(@ClearHash, qw/PriorityAsString/);
 
 =head1 Database connection
 
@@ -1813,6 +1819,66 @@ to Articles when they are included in a message.
 
 Set($LinkArticlesOnInclude, 1);
 
+=item C<%NumericalPriority>
+
+Disable string priorities
+
+    Set($NumericalPriority, 0);
+
+=cut
+
+Set($NumericalPriority, 0);
+
+=item C<%PriorityAsString>
+
+RT can assign a priority value to tickets. Priority is stored as an
+integer in the database, but RT supports mapping strings to numerical
+values. For example, the default mapping is:
+
+    Set(%PriorityAsString, Low => 0, Medium => 50, High => 100);
+
+Redefine C<%PriorityAsString> in C<RT_SiteConfig.pm> to set site
+priority strings.
+
+=cut
+
+Set(%PriorityAsString, Low => 0, Medium => 50, High => 100);
+
+=item C<%PriorityAsStringOrder>
+
+Administrators can alter the order of priority strings as they appear
+in selection drop-downs with C<@PriorityStringOrder>. Administrators
+can also use this setting to limit the available priority strings on
+ticket update pages. When this options is defined, scrips and other RT
+code will still have access to all of the priority strings defined in
+C<%PriorityAsString>. To set a priority string order:
+
+    Set(@PriorityAsStringOrder, qw(Low Medium High));
+
+=cut
+
+=item C<%PriorityAsStringQueues>
+
+RT supports different priority string mappings for individual queues
+with C<%PriorityAsStringQueues>. Use queue names as keys in this
+hash. Then define priority string-number hash maps for each queue's
+value. Tickets in queues that aren't defined in this hash will fall
+back to RT's numerical priorities.
+
+When C<%PriorityAsStringQueues> is set, RT ignores both
+C<%PriorityAsString> and C<@PriorityAsStringOrder>. Administrators do
+not need to define C<%PriorityAsStringQueues> or C<%PriorityAsString>
+when they set C<%PriorityAsStringQueues>.
+
+To set per-queue priority strings:
+
+    Set(%PriorityAsStringQueues,
+      General => { Low => 0, Medium => 50, High => 100 },
+      Binary  => { Low => 0, High => 10 },
+    );
+
+=cut
+
 =back
 
 =head1 Assets
diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index e73273012..68ca885d4 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -1617,7 +1617,7 @@ sub SetFromConfig {
     if ( exists $OPTIONS{$name} ) {
         if ( $type eq 'HASH' ) {
             $args{'Value'} = [
-                @{ $args{'Value'} },
+                grep (/$name/, @{$OPTIONS{ClearHash}}) ? () : @{ $args{'Value'} },
                 @{ $args{'Value'} }%2? (undef) : (),
                 $self->Get( $name ),
             ];
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 08169fb9c..0b1e5fdc7 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -3316,7 +3316,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of InitialPriority.
 (In the database, InitialPriority is stored as int(11).)
 
+=head2 InitialPriorityAsString
 
+Returns the current mapped string value of InitialPriority.
 
 =head2 SetInitialPriority VALUE
 
@@ -3334,7 +3336,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of FinalPriority.
 (In the database, FinalPriority is stored as int(11).)
 
+=head2 FinalPriorityAsString
 
+Returns the current mapped string value of FinalPriority.
 
 =head2 SetFinalPriority VALUE
 
@@ -3352,7 +3356,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of Priority.
 (In the database, Priority is stored as int(11).)
 
+=head2 PriorityAsString
 
+Returns the current mapped string value of Priority.
 
 =head2 SetPriority VALUE
 
@@ -3697,6 +3703,47 @@ sub Serialize {
     return %store;
 }
 
+# Returns String: Various Ticket Priorities as either a string or integer
+sub PriorityAsString {
+    my $self = shift;
+    return $self->_PriorityAsString($self->Priority);
+}
+
+sub InitialPriorityAsString {
+    my $self = shift;
+    return $self->_PriorityAsString( $self->InitialPriority );
+}
+
+sub FinalPriorityAsString {
+    my $self=shift;
+    return $self->_PriorityAsString( $self->FinalPriority );
+}
+
+sub _PriorityAsString {
+    my $self = shift;
+    my $priority = shift;
+    return undef unless defined $priority && length $priority;
+
+    my %map;
+    my $queues = RT->Config->Get('PriorityAsStringQueues');
+    if (@_) {
+        %map = %{ shift(@_) };
+    } elsif ($queues and $queues->{$self->QueueObj->Name}) {
+        %map = %{ $queues->{$self->QueueObj->Name} };
+    } else {
+        %map = RT->Config->Get('PriorityAsString');
+    }
+
+    # Count from high down to low until we find one that our number is
+    # greater than or equal to.
+    if ( values %map ) {
+        foreach my $label ( sort { $map{$b} <=> $map{$a} } keys %map ) {
+            return $label if $priority >= $map{ $label };
+        };
+    }
+    return "unknown";
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 089ccea11..0a3390d41 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -352,6 +352,42 @@ if(RT->Config->Get('DisplayTotalTimeWorked')) {
     }
 }
 
+my $printer = sub {
+    my ($class, $string) = @_;
+    return '' unless defined $string && length $string;
+
+    my $request_path = $HTML::Mason::Commands::r->path_info;
+    if ($request_path and $request_path =~ /Results\.tsv/) {
+        return loc($string);
+    }
+
+    my $escaped = $m->interp->apply_escapes($string, 'h');
+    my $loc_escaped = $m->interp->apply_escapes(loc($string), 'h');
+    return \( qq{<span class="ticket-info-$class-}. lc($escaped) .qq{">$loc_escaped</span>} );
+};
+
+foreach my $field (qw(Priority InitialPriority FinalPriority)) {
+    $COLUMN_MAP->{ $field .'Number' } ||= $COLUMN_MAP->{ $field };
+
+    my $class = lc($field);
+    $class =~ s/(?=<.)(?=priority)/-/;
+
+    my $method = $field .'AsString';
+
+    my %queues = RT->Config->Get('PriorityAsStringQueues') || ();
+    if (not keys %queues) {
+        $COLUMN_MAP->{ $field }{'value'} = sub {
+            return $printer->( $class, $_[0]->$method() );
+        };
+    } else {
+        $COLUMN_MAP->{ $field }{'value'} = sub {
+            return $queues{$_[0]->QueueObj->Name}
+                ? $printer->( $class, $_[0]->$method() )
+                : $_[0]->$field;
+        };
+    }
+}
+
 $m->callback( GenericMap => $GenericMap, COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
 </%init>
diff --git a/share/html/Elements/SelectPriority b/share/html/Elements/SelectPriority
index 078d85df7..f09b0d5de 100644
--- a/share/html/Elements/SelectPriority
+++ b/share/html/Elements/SelectPriority
@@ -45,11 +45,57 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+% if (%map) {
+<select class="select-priority" name="<% $Name %>">
+%     unless ( defined $Default ) {
+<option value="">-</option>
+%     }
+<%PERL>
+foreach my $label ( @order ) {
+    my ($value, $selected);
+    if ( $label eq $default_label ) {
+        ($value, $selected) = ($Default, 'selected="selected"');
+    } else {
+        ($value, $selected) = ($map{ $label }, '');
+    }
+</%PERL>
+<option class="<% lc $label %>" value="<% $value %>" <% $selected |n %>><% loc($label) %></option>
+% }
+</select>
+% } else {
 <input name="<% $Name %>" value="<% $Default %>" size="5" />
+% }
 <%ARGS>
 $Name => 'Priority'
-$Default => ''
+$Default => undef
+$QueueObj => undef
+$PriorityStringMap => undef
 </%ARGS>
 <%INIT>
+
+my $priority_is_string = undef;
+my @order;
+my $default_label = '';
+my %map = ();
+
+if ($PriorityStringMap) {
+    %map = %{$PriorityStringMap};
+} elsif ($QueueObj and ! RT->Config->Get('NumericalPriority')) {
+    my %config = RT->Config->Get('PriorityAsStringQueues') ?  RT->Config->Get('PriorityAsStringQueues') : ();
+    %map = %config && $config{$QueueObj->Name} ? %{$config{$QueueObj->Name}} : RT->Config->Get('PriorityAsString');
+}
+
+if (%map) {
+    if (RT->Config->Get('PriorityAsStringOrder')) {
+    @order = grep {exists $map{$_}} RT->Config->Get('PriorityAsStringOrder');
+    } else {
+    @order = sort { $map{$a} <=> $map{$b} } keys %map;
+    }
+
+    if ( defined $Default && length $Default ) {
+    $default_label = RT::Ticket->_PriorityAsString( $Default, \%map ) || '';
+    }
+}
+
 $Default = '' unless defined $Default;
 </%INIT>
diff --git a/share/html/Search/Elements/PickBasics b/share/html/Search/Elements/PickBasics
index 3f2ed237a..682058d01 100644
--- a/share/html/Search/Elements/PickBasics
+++ b/share/html/Search/Elements/PickBasics
@@ -223,6 +223,18 @@ my @lines = (
     },
 );
 
+my %priority_strings = RT->Config->Get('PriorityAsStringQueues') || ();
+if ( !RT->Config->Get('NumericalPriority') ) {
+    my ($priority_dropdown) = grep {$_->{Name} eq "Priority"} @lines;
+    my %priority_map = ( '-' => '' );
+    for my $queue (keys %queues) {
+    for my $priority (keys %{$priority_strings{$queue}}) {
+        $priority_map{ keys %queues > 1 ? "$queue: $priority" : "$priority" } = $priority_strings{$queue}{$priority};
+    }
+    }
+    $priority_dropdown->{Value}{Arguments}{PriorityStringMap} = \%priority_map;
+}
+
 $m->callback( Conditions => \@lines );
 
 </%INIT>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index 26dc216b0..9352eefc1 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -271,11 +271,13 @@
 <td><& /Elements/SelectPriority,
     Name => "InitialPriority",
     Default => $ARGS{InitialPriority} ? $ARGS{InitialPriority} : $QueueObj->DefaultValue('InitialPriority'),
+    QueueObj => $QueueObj,
 &></td></tr>
 <tr><td class="label"><&|/l&>Final Priority</&>:</td>
 <td><& /Elements/SelectPriority,
     Name => "FinalPriority",
     Default => $ARGS{FinalPriority} ? $ARGS{FinalPriority} : $QueueObj->DefaultValue('FinalPriority'),
+    QueueObj => $QueueObj,
 &></td></tr>
 <tr><td class="label"><&|/l&>Time Estimated</&>:</td>
 <td>
diff --git a/share/html/Ticket/Elements/EditBasics b/share/html/Ticket/Elements/EditBasics
index c4505e770..284e7d407 100644
--- a/share/html/Ticket/Elements/EditBasics
+++ b/share/html/Ticket/Elements/EditBasics
@@ -58,6 +58,16 @@ if ($TicketObj) {
     $QueueObj ||= $TicketObj->QueueObj;
 }
 
+#my %queue_priority_strings = RT->Config->Get('PriorityAsStringQueues');
+#
+## Leave it as-is if all queues use PriorityAsString; the overridden
+## /Elements/SelectPriority catches this case and always shows the
+## drop-down
+##return unless keys %as_string;
+#
+## Only applies if the ticket is in a PriorityAsString queue
+##return unless $TicketObj and $as_string{$TicketObj->QueueObj->Name};
+
 unless ( @fields ) {
     my $subject = $defaults{'Subject'} || $TicketObj->Subject;
     @fields = (
@@ -128,6 +138,7 @@ unless ( @fields ) {
                     args => {
                         Name => $field,
                         Default => $defaults{$field} || $TicketObj->$field,
+                QueueObj => $QueueObj,
                     }
                 }
             } ('Priority', 'Final Priority')
diff --git a/share/html/Ticket/Elements/ShowPriority b/share/html/Ticket/Elements/ShowPriority
index c465d4875..2d450ce8c 100644
--- a/share/html/Ticket/Elements/ShowPriority
+++ b/share/html/Ticket/Elements/ShowPriority
@@ -45,7 +45,22 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+% if ( !RT->Config->Get('NumericalPriority') ) {
+%   my $current = $Ticket->PriorityAsString || '';
+%   my $final = $Ticket->FinalPriorityAsString || '';
+<span class="ticket-info-priority-<% $CSSClass->(lc($current)) %>"><% loc($current) %></span>/\
+<span class="ticket-info-final-priority-<% $CSSClass->(lc($final)) %>"><% loc($final) %></span>
+% } else {
 <% $Ticket->Priority %>/<% $Ticket->FinalPriority || ''%>
+% }
 <%ARGS>
 $Ticket => undef
 </%ARGS>
+<%INIT>
+my $CSSClass = sub {
+    my $value = shift;
+    return '' unless defined $value;
+    $value =~ s/[^A-Za-z0-9_-]/_/g;
+    return $value;
+};
+</%INIT>
diff --git a/t/web/mobile.t b/t/web/mobile.t
index 3f32e49e6..831bf6652 100644
--- a/t/web/mobile.t
+++ b/t/web/mobile.t
@@ -82,7 +82,7 @@ $m->content_contains( 'ticket1', 'subject' );
 $m->content_contains( 'open', 'status' );
 $m->content_contains( 'cc at example.com', 'cc' );
 $m->content_contains( 'admincc at example.com', 'admincc' );
-$m->content_contains( '13/93', 'priority' );
+$m->text_contains( 'Low/Medium', 'priority' );
 $m->content_contains( '2 hour', 'time estimates' );
 $m->content_contains( '30 min', 'time worked' );
 $m->content_contains( '60 min', 'time left' );

commit 4504c9ba4c554bf6130e92fdf30064b6ef27603d
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Thu Jan 3 11:31:31 2019 -0500

    Test that PriorityAsString hash is reset when set from siteconfig
    
    We do not want to keep the old key values of the default PriorityAsString
    hash, but instead only take the new hash provided in RT_SiteConfig.pm.

diff --git a/t/api/config.t b/t/api/config.t
index b87531139..302996de9 100644
--- a/t/api/config.t
+++ b/t/api/config.t
@@ -1,7 +1,11 @@
 use strict;
 use warnings;
 use RT;
-use RT::Test nodb => 1, tests => undef;
+
+use RT::Test nodb => 1, tests => undef, config => <<'CONFIG';
+Set(%PriorityAsString, Green => 1, Yellow => 50, Red => 100);
+CONFIG
+
 use Test::Warn;
 
 ok(
@@ -46,4 +50,13 @@ warning_like {RT::Config->PostLoadCheck} qr{rudder},
 my @canonical_encodings = RT::Config->Get('EmailInputEncodings');
 is_deeply(\@encodings, \@canonical_encodings, 'Got correct encoding list');
 
-done_testing;
\ No newline at end of file
+my %PriorityAsString = RT::Config->Get('PriorityAsString');
+
+foreach (qw/Low Medium High/) {
+    is $PriorityAsString{$_}, undef , 'Does not have default config values for PriorityAsString';
+}
+foreach (qw/Green Yellow Red/) {
+    ok $PriorityAsString{$_} ,'SiteConfig value for PriorityAsString overrode default value completly';
+}
+
+done_testing;

commit 53affddf2d0deb03628c60a7b85ce923ece4c499
Author: michel <michel at bestpractical.com>
Date:   Wed May 8 12:35:17 2019 +0200

    cored priority as string
    
    adds final proposal for the feature:
    
    Unify and streamline PriorityAsString configuration
    
    As an extension, PriorityAsString grew additional configuration
    options as features were added. As a core feature, we want to
    add as few new configuration options as possible while still
    providing the needed features.
    
    The updated configuration provides options to handle global
    configuration, per queue settings, and sensible defaults.

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 169d5e22a..60731bc9b 100644
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1720,6 +1720,90 @@ Set this to 1 to hide unset fields.
 
 Set($HideUnsetFieldsOnDisplay, 0);
 
+=item C<%EnablePriorityAsString>
+
+Set this to C<0> to disable string priorities and only use
+numerical ones
+
+=cut
+
+Set($EnablePriorityAsString, 1);
+
+=item C<%PriorityAsString>
+
+RT can assign a priority value to tickets. Priority is stored as an
+integer in the database, but RT supports mapping strings to numerical
+values. 
+
+RT supports different priority string mappings for individual queues
+with C<%PriorityAsString>. 
+
+For example, the default mapping is:
+
+    Set(%PriorityAsString,
+      Default => { Low => 0, Medium => 50, High => 100 },
+    )
+
+Use queue names as keys in this hash. 
+
+Values in the hash define the mapping:
+
+=over 4
+
+=item 
+
+C<0> sets the queue to use numerical priorities:
+
+    NumQueue => 0
+
+=item 
+
+a hash C<< { string => numerical_value,... } >> maps each string to
+the numerical value:
+
+    QueueWith3Levels => { Low => 0, Medium => 50, High => 100 }
+
+=item
+
+an array C<< [ string => numerical_value, ... ] >> maps each string to
+the numerical value, and additionaly tells RT to display strings in the
+order they were given in drop-down menus:
+
+      Ordered => [ Low => 0, High => 100, Medium => 50 ]
+    
+In this case the drop-down menus used to choose the priority in RT will
+display Low/High/Medium, in this order
+
+=back
+
+Tickets in queues that aren't defined in this hash will use the mapping
+defined for C<Default>.
+
+A complete exampl of per-queue priority strings:
+
+    Set(%PriorityAsString,
+      # all queues not listed here will use this mapping
+      Default    => { Low => 0, Medium => 50, High => 100 },
+      # 
+      General    => { Low => 0, High => 1 },
+      ColorQueue => { Green => 0, Yellow => 50, Red => 100 },
+      # drop-downs will display in order Low/High/Medium
+      LHM        => [ Low => 0, High => 100, Medium => 50 ],
+      # use numerical priorities
+      NumQueue   => 0,
+    );
+
+Redefine C<%PriorityAsString> in C<RT_SiteConfig.pm> to set site
+priority strings.
+
+The default is 3 levels of priority: Low, Medium and High 
+
+=cut
+
+    Set(%PriorityAsString,
+      Default => { Low => 0, Medium => 50, High => 100 },
+    );
+
 =back
 
 =head2 Self Service Interface
diff --git a/etc/RT_SiteConfig.pm b/etc/RT_SiteConfig.pm
deleted file mode 100644
index 9944ebe97..000000000
--- a/etc/RT_SiteConfig.pm
+++ /dev/null
@@ -1,35 +0,0 @@
-use utf8;
-
-# Any configuration directives you include  here will override
-# RT's default configuration file, RT_Config.pm
-#
-# To include a directive here, just copy the equivalent statement
-# from RT_Config.pm and change the value. We've included a single
-# sample value below.
-#
-# If this file includes non-ASCII characters, it must be encoded in
-# UTF-8.
-#
-# This file is actually a perl module, so you can include valid
-# perl code, as well.
-#
-# The converse is also true, if this file isn't valid perl, you're
-# going to run into trouble. To check your SiteConfig file, use
-# this command:
-#
-#   perl -c /path/to/your/etc/RT_SiteConfig.pm
-#
-# You must restart your webserver after making changes to this file.
-#
-
-# You may also split settings into separate files under the etc/RT_SiteConfig.d/
-# directory.  All files ending in ".pm" will be parsed, in alphabetical order,
-# after this file is loaded.
-
-Set( $rtname, 'example.com');
-
-# You must install Plugins on your own, this is only an example
-# of the correct syntax to use when activating them:
-#     Plugin( "RT::Authen::ExternalAuth" );
-
-1;
diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index 68ca885d4..c0cb7f570 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -1813,6 +1813,113 @@ sub EnableExternalAuth {
     return;
 }
 
+=head2 Methods for specific options
+
+=head2 PriorityMap( <optional_queue_name>)
+
+Returns a hash ref C<< { <priority_as_string> => <priority_value>, ... } >> 
+
+If no queue name is given uses the configuration for C<'Default'>.
+
+If the queue has no C<PriorityAsString> option, uses the one for  C<'Default'>.
+
+Returns C<undef> if C<EnablePriorityAsString> is set to 0, if the
+queue has C<PriorityAsString> switched off (by setting it to C<0>) or if no 
+map is available.
+
+Logs an error if a PriorityAsString is found but it is neither a hash nor an 
+array, nor 0.
+
+=cut 
+
+sub PriorityMap
+  { my $self  = shift;
+    my $queue = shift || 'Default';
+
+    my $option = $self->_get_PriorityAsString_for_queue( $queue );
+    return undef if ! $option;
+
+    my $map;
+    if ( ref $option eq 'HASH' ) {
+        # regular map 
+        $map = $option
+    } elsif ( ref $option eq 'ARRAY' ) {
+        # order is irrelevent here, load the array as a hash
+        $map = { @$option };
+    } else {
+        # try to diagnose the problem by showing some details about the map
+        # note: this could also be done when the config is loaded
+
+        # where was the map defined
+        my $queues= $self->Get('PriorityAsString');
+        my $real_queue = defined $queues->{$queue}  ? "queue $queue"
+                       : defined $queues->{Default} ? 'Default queue'
+                       :                              'cannot happen';
+
+        # what's in the map definition 
+        my $option_desc = ref $option         ? "map is a " . ref( $option) 
+                        : length $option < 20 ? $option 
+                        :                     substr( $option, 0, 17) . '...';
+
+        $RT::Logger->error("Wrong priority map for $real_queue: $option_desc");            
+        return undef;
+    }
+    return $map;
+  }
+
+=head2 PriorityMapOrder( <optional_queue_name>)
+
+Returns an array of priority strings, in the proper order for display.
+
+The order is either given in the C<PriorityAsString> option by using an
+array for the queue, or is based on the numerical values of the options
+(lower values first).
+
+=cut
+
+sub PriorityMapOrder
+  { my $self  = shift;
+    my $queue = shift || 'Default';
+
+    my $option = $self->_get_PriorityAsString_for_queue( $queue );
+    return undef if ! $option;
+
+    my @ordered;
+    if ( ref $option eq 'HASH' ) {
+        # hash: sort it on the value
+        @ordered = sort { $option->{$a} <=> $option->{$b} } keys %$option
+    } elsif ( ref $option eq 'ARRAY' ) {
+        # array: use the array order, extract every other element
+        foreach( my $i=0; $i<@$option; $i+=2) {
+            push @ordered, $option->[$i];
+        }
+    } else {
+        return undef;
+    }
+
+    return \@ordered;
+
+  }
+
+# internal method, _get_PriorityAsString_for_queue( <queue name> )
+# returns 
+
+sub _get_PriorityAsString_for_queue
+  { my $self  = shift;
+    my $queue = shift;
+
+    return undef if ! $self->Get( 'EnablePriorityAsString' );
+
+    my $queues = $self->Get( 'PriorityAsString' );
+    return undef if ! $queues;
+
+    my $map = defined $queues->{$queue} ? $queues->{$queue}
+            : defined $queues->{Default}? $queues->{Default}
+            :                             undef;
+
+    return $map;
+  }
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 4c2f5fb62..f7418f577 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -772,6 +772,7 @@ sub _Set {
             $args{'TransactionType'} = ($args{'Value'} == 1) ? "Disabled" : "Enabled";
             delete $args{'Field'};
         }
+
         my ( undef, undef, $TransObj ) = $self->_NewTransaction(
             Type      => $args{'TransactionType'},
             Field     => $args{'Field'},
@@ -1194,6 +1195,11 @@ sub SetDefaultValue {
         },
     );
 
+    if( $args{Name}=~ /^(Initial|Final)Priority/ ) {
+        $old_value= $self->_PriorityAsString( $old_value );
+        $new_value= $self->_PriorityAsString( $new_value );
+    }
+
     if ( $ret ) {
         return ( $ret, $self->loc( 'Default value of [_1] changed from [_2] to [_3]', $args{Name}, $old_value, $new_value ) );
     }
@@ -1202,6 +1208,12 @@ sub SetDefaultValue {
     }
 }
 
+sub _PriorityAsString {
+    my( $self, $priority)= @_;
+    my $map = RT->Config->PriorityMap( $self->Name );
+    return RT::Ticket->_PriorityAsString( $priority, $map );
+}
+
 sub SLA {
     my $self = shift;
     my $value = shift;
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 0b1e5fdc7..32e8053a1 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -2801,10 +2801,18 @@ sub _Set {
     return ( $ret, $msg ) unless $args{'RecordTransaction'};
 
     my $trans;
+
+    my $New= $args{'Value'};
+    # *Priority fields may need to be translated
+    if( $args{'Field'} =~ m{^(Initial|Final)?Priority$}) { 
+        $Old= $self->_PriorityAsString( $Old ); 
+        $New= $self->_PriorityAsString( $New );
+    }
+
     ( $ret, $msg, $trans ) = $self->_NewTransaction(
         Type      => $args{'TransactionType'},
         Field     => $args{'Field'},
-        NewValue  => $args{'Value'},
+        NewValue  => $New,
         OldValue  => $Old,
         TimeTaken => $args{'TimeTaken'},
     );
@@ -3706,7 +3714,7 @@ sub Serialize {
 # Returns String: Various Ticket Priorities as either a string or integer
 sub PriorityAsString {
     my $self = shift;
-    return $self->_PriorityAsString($self->Priority);
+    return $self->_PriorityAsString( $self->Priority );
 }
 
 sub InitialPriorityAsString {
@@ -3724,26 +3732,29 @@ sub _PriorityAsString {
     my $priority = shift;
     return undef unless defined $priority && length $priority;
 
-    my %map;
-    my $queues = RT->Config->Get('PriorityAsStringQueues');
-    if (@_) {
-        %map = %{ shift(@_) };
-    } elsif ($queues and $queues->{$self->QueueObj->Name}) {
-        %map = %{ $queues->{$self->QueueObj->Name} };
-    } else {
-        %map = RT->Config->Get('PriorityAsString');
+    my $map;
+    if( @_ ) {
+        $map = shift;
+    } else { 
+        my $queue_name = $self->QueueObj->Name;
+        $map = RT->Config->PriorityMap( $queue_name);
     }
 
-    # Count from high down to low until we find one that our number is
-    # greater than or equal to.
-    if ( values %map ) {
-        foreach my $label ( sort { $map{$b} <=> $map{$a} } keys %map ) {
-            return $label if $priority >= $map{ $label };
-        };
-    }
-    return "unknown";
+    return $priority if ! $map;
+
+    my @orderedLabels = sort { $map->{$b} <=> $map->{$a} }  keys %$map;
+
+    # return the label for the first priority <= $priority
+    foreach my $label ( @orderedLabels ) {
+        return $label if $priority >= $map->{ $label };
+    };
+    # if we get here the priority is lower than the lowest in the map
+    # return the label associated with the lowest priority
+    return $orderedLabels[-1];
+
 }
 
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/Admin/Queues/DefaultValues.html b/share/html/Admin/Queues/DefaultValues.html
index aff93cc0b..aec3ce4eb 100644
--- a/share/html/Admin/Queues/DefaultValues.html
+++ b/share/html/Admin/Queues/DefaultValues.html
@@ -59,11 +59,13 @@
     <td><& /Elements/SelectPriority,
         Name => "InitialPriority",
         Default => $queue->DefaultValue('InitialPriority'),
+        QueueObj  => $queue,
     &></td></tr>
     <tr><td class="label"><&|/l&>Final Priority</&>:</td>
     <td><& /Elements/SelectPriority,
         Name => "FinalPriority",
         Default => $queue->DefaultValue('FinalPriority'),
+        QueueObj  => $queue,
     &><br /><span><em><&|/l&>requires running rt-crontool</&></em></span></td></tr>
     <& /Elements/EditCustomFields,
         Object => RT::Ticket->new($session{CurrentUser}),
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 0a3390d41..c336a2ac3 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -366,6 +366,8 @@ my $printer = sub {
     return \( qq{<span class="ticket-info-$class-}. lc($escaped) .qq{">$loc_escaped</span>} );
 };
 
+my $queues = RT->Config->Get('PriorityAsString') || {};
+
 foreach my $field (qw(Priority InitialPriority FinalPriority)) {
     $COLUMN_MAP->{ $field .'Number' } ||= $COLUMN_MAP->{ $field };
 
@@ -374,14 +376,13 @@ foreach my $field (qw(Priority InitialPriority FinalPriority)) {
 
     my $method = $field .'AsString';
 
-    my %queues = RT->Config->Get('PriorityAsStringQueues') || ();
-    if (not keys %queues) {
+    if (not keys %$queues) {
         $COLUMN_MAP->{ $field }{'value'} = sub {
             return $printer->( $class, $_[0]->$method() );
         };
     } else {
         $COLUMN_MAP->{ $field }{'value'} = sub {
-            return $queues{$_[0]->QueueObj->Name}
+            return $queues->{$_[0]->QueueObj->Name}
                 ? $printer->( $class, $_[0]->$method() )
                 : $_[0]->$field;
         };
diff --git a/share/html/Elements/SelectPriority b/share/html/Elements/SelectPriority
index f09b0d5de..a724e4a95 100644
--- a/share/html/Elements/SelectPriority
+++ b/share/html/Elements/SelectPriority
@@ -78,24 +78,16 @@ my @order;
 my $default_label = '';
 my %map = ();
 
-if ($PriorityStringMap) {
-    %map = %{$PriorityStringMap};
-} elsif ($QueueObj and ! RT->Config->Get('NumericalPriority')) {
-    my %config = RT->Config->Get('PriorityAsStringQueues') ?  RT->Config->Get('PriorityAsStringQueues') : ();
-    %map = %config && $config{$QueueObj->Name} ? %{$config{$QueueObj->Name}} : RT->Config->Get('PriorityAsString');
-}
-
-if (%map) {
-    if (RT->Config->Get('PriorityAsStringOrder')) {
-    @order = grep {exists $map{$_}} RT->Config->Get('PriorityAsStringOrder');
-    } else {
-    @order = sort { $map{$a} <=> $map{$b} } keys %map;
-    }
-
-    if ( defined $Default && length $Default ) {
-    $default_label = RT::Ticket->_PriorityAsString( $Default, \%map ) || '';
+if( $QueueObj ) {
+    if( my $map = RT->Config->PriorityMap( $QueueObj->Name ) ) {
+        %map   = %$map;
+        @order = @{RT->Config->PriorityMapOrder( $QueueObj->Name)};
+        if ( defined $Default && length $Default ) {
+        $default_label = RT::Ticket->_PriorityAsString( $Default, \%map ) || '';
+        }
     }
 }
 
+
 $Default = '' unless defined $Default;
 </%INIT>
diff --git a/share/html/Search/Elements/PickBasics b/share/html/Search/Elements/PickBasics
index 682058d01..068c829cd 100644
--- a/share/html/Search/Elements/PickBasics
+++ b/share/html/Search/Elements/PickBasics
@@ -223,13 +223,14 @@ my @lines = (
     },
 );
 
-my %priority_strings = RT->Config->Get('PriorityAsStringQueues') || ();
-if ( !RT->Config->Get('NumericalPriority') ) {
+
+if ( RT->Config->Get('EnablePriorityAsString') ) {
     my ($priority_dropdown) = grep {$_->{Name} eq "Priority"} @lines;
     my %priority_map = ( '-' => '' );
     for my $queue (keys %queues) {
-    for my $priority (keys %{$priority_strings{$queue}}) {
-        $priority_map{ keys %queues > 1 ? "$queue: $priority" : "$priority" } = $priority_strings{$queue}{$priority};
+    my $queue_priority_map= RT::Config->PriorityMap( $queue);
+    for my $priority ( keys %$queue_priority_map ) {
+        $priority_map{ keys %queues > 1 ? "$queue: $priority" : "$priority" } = $queue_priority_map->{$priority};
     }
     }
     $priority_dropdown->{Value}{Arguments}{PriorityStringMap} = \%priority_map;

-----------------------------------------------------------------------


More information about the rt-commit mailing list