[Rt-commit] rt branch, 4.2/generalize-lifecycles, created. rt-4.1.5-14-g71e6b11

Alex Vandiver alexmv at bestpractical.com
Mon Dec 10 16:10:55 EST 2012


The branch, 4.2/generalize-lifecycles has been created
        at  71e6b11eabc04cfeca749997de0244bb637e61fe (commit)

- Log -----------------------------------------------------------------
commit e995af9a83e058d42354047ba773148fad2b8ca9
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Dec 7 15:08:28 2012 -0500

    Factor out common code for setting Started and Resolved

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 7faa223..c643a2d 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -1389,36 +1389,10 @@ sub SetQueue {
             return ( 0, $self->loc("Couldn't load copy of ticket #[_1].", $self->Id) );
         }
 
-        my $now = RT::Date->new( $self->CurrentUser );
-        $now->SetToNow;
-
-        my $old_status = $clone->Status;
-
-        #If we're changing the status from initial in old to not intial in new,
-        # record that we've started
-        if ( $old_lifecycle->IsInitial($old_status) && !$new_lifecycle->IsInitial($new_status)  && $clone->StartedObj->Unix == 0 ) {
-            #Set the Started time to "now"
-            $clone->_Set(
-                Field             => 'Started',
-                Value             => $now->ISO,
-                RecordTransaction => 0
-            );
-        }
-
-        #When we close a ticket, set the 'Resolved' attribute to now.
-        # It's misnamed, but that's just historical.
-        if ( $new_lifecycle->IsInactive($new_status) ) {
-            $clone->_Set(
-                Field             => 'Resolved',
-                Value             => $now->ISO,
-                RecordTransaction => 0,
-            );
-        }
-
-        #Actually update the status
-        my ($val, $msg)= $clone->_Set(
-            Field             => 'Status',
-            Value             => $new_status,
+        my ($val, $msg) = $clone->_SetStatus(
+            Lifecycle         => $old_lifecycle,
+            NewLifecycle      => $new_lifecycle,
+            Status            => $new_status,
             RecordTransaction => 0,
         );
         $RT::Logger->error( 'Status change failed on queue change: '. $msg )
@@ -2701,15 +2675,37 @@ sub SetStatus {
         return ( 0, $self->loc('That ticket has unresolved dependencies') );
     }
 
+    return $self->_SetStatus(
+        Status     => $args{Status},
+        SetStarted => $args{SetStarted},
+    );
+}
+
+sub _SetStatus {
+    my $self = shift;
+    my %args = (
+        Status => undef,
+        SetStarted => 1,
+        RecordTransaction => 1,
+        Lifecycle => $self->QueueObj->Lifecycle,
+        @_,
+    );
+    $args{NewLifecycle} ||= $args{Lifecycle};
+
     my $now = RT::Date->new( $self->CurrentUser );
     $now->SetToNow();
 
     my $raw_started = RT::Date->new(RT->SystemUser);
     $raw_started->Set(Format => 'ISO', Value => $self->__Value('Started'));
 
-    #If we're changing the status from new, record that we've started
-    if ( $args{SetStarted} && $lifecycle->IsInitial($old) && !$lifecycle->IsInitial($new) && !$raw_started->Unix) {
-        #Set the Started time to "now"
+    my $old = $self->__Value('Status');
+
+    # If we're changing the status from new, record that we've started
+    if ( $args{SetStarted}
+             && $args{Lifecycle}->IsInitial($old)
+             && !$args{NewLifecycle}->IsInitial($args{Status})
+             && !$raw_started->Unix) {
+        # Set the Started time to "now"
         $self->_Set(
             Field             => 'Started',
             Value             => $now->ISO,
@@ -2717,9 +2713,9 @@ sub SetStatus {
         );
     }
 
-    #When we close a ticket, set the 'Resolved' attribute to now.
+    # When we close a ticket, set the 'Resolved' attribute to now.
     # It's misnamed, but that's just historical.
-    if ( $lifecycle->IsInactive($new) ) {
+    if ( $args{NewLifecycle}->IsInactive($args{Status}) ) {
         $self->_Set(
             Field             => 'Resolved',
             Value             => $now->ISO,
@@ -2727,13 +2723,14 @@ sub SetStatus {
         );
     }
 
-    #Actually update the status
+    # Actually update the status
     my ($val, $msg)= $self->_Set(
         Field           => 'Status',
         Value           => $args{Status},
         TimeTaken       => 0,
         CheckACL        => 0,
         TransactionType => 'Status',
+        RecordTransaction => $args{RecordTransaction},
     );
     return ($val, $msg);
 }

commit 3b69dfcf2070b3ff322ecab57a8c3d235352107d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Dec 7 12:53:00 2012 -0500

    Allow lifecycles to be applied to different objects types
    
    Refactor ticket-specific methods of tickets to RT::Lifecycle::Ticket,
    and re-bless RT::Lifecycle objects on creation to the appropriate
    sublclass based on 'type'.  This opens the possibility of objects that
    are not tickets using lifecycles for their 'Status' columns.

diff --git a/lib/RT/Lifecycle.pm b/lib/RT/Lifecycle.pm
index 056599e..b66276b 100644
--- a/lib/RT/Lifecycle.pm
+++ b/lib/RT/Lifecycle.pm
@@ -141,6 +141,10 @@ sub Load {
     $self->{'name'} = $name;
     $self->{'data'} = $LIFECYCLES_CACHE{ $name };
 
+    my $type = $self->{'data'}{'type'} || 'ticket';
+    $type = "RT::Lifecycle::".ucfirst($type);
+    bless $self, $type if $type->require;
+
     return $self;
 }
 
@@ -152,34 +156,22 @@ Returns sorted list of the lifecycles' names.
 
 sub List {
     my $self = shift;
+    my $for = shift || 'ticket';
 
     $self->FillCache unless keys %LIFECYCLES_CACHE;
 
-    return sort grep length && $_ ne '__maps__', keys %LIFECYCLES_CACHE;
+    return sort grep {$LIFECYCLES_CACHE{$_}{type} eq $for}
+        grep length && $_ ne '__maps__', keys %LIFECYCLES_CACHE;
 }
 
 =head2 Name
 
-Returns name of the laoded lifecycle.
+Returns name of the loaded lifecycle.
 
 =cut
 
 sub Name { return $_[0]->{'name'} }
 
-=head2 Queues
-
-Returns L<RT::Queues> collection with queues that use this lifecycle.
-
-=cut
-
-sub Queues {
-    my $self = shift;
-    require RT::Queues;
-    my $queues = RT::Queues->new( RT->SystemUser );
-    $queues->Limit( FIELD => 'Lifecycle', VALUE => $self->Name );
-    return $queues;
-}
-
 =head2 Getting statuses and validating.
 
 Methods to get statuses in different sets or validating them.
@@ -342,52 +334,6 @@ sub DefaultStatus {
     return $self->{data}{defaults}{ $situation };
 }
 
-=head3 DefaultOnCreate
-
-Returns the status that should be used by default
-when ticket is created.
-
-=cut
-
-sub DefaultOnCreate {
-    my $self = shift;
-    return $self->DefaultStatus('on_create');
-}
-
-
-=head3 DefaultOnMerge
-
-Returns the status that should be used when tickets
-are merged.
-
-=cut
-
-sub DefaultOnMerge {
-    my $self = shift;
-    return $self->DefaultStatus('on_merge');
-}
-
-=head3 ReminderStatusOnOpen
-
-Returns the status that should be used when reminders are opened.
-
-=cut
-
-sub ReminderStatusOnOpen {
-    my $self = shift;
-    return $self->DefaultStatus('reminder_on_open') || 'open';
-}
-
-=head3 ReminderStatusOnResolve
-
-Returns the status that should be used when reminders are resolved.
-
-=cut
-
-sub ReminderStatusOnResolve {
-    my $self = shift;
-    return $self->DefaultStatus('reminder_on_resolve') || 'resolved';
-}
 
 =head2 Transitions, rights, labels and actions.
 
@@ -641,6 +587,10 @@ sub FillCache {
     %LIFECYCLES_CACHE = %LIFECYCLES = %$map;
     $_ = { %$_ } foreach values %LIFECYCLES_CACHE;
 
+    for my $lifecycles (values %LIFECYCLES_CACHE) {
+        $lifecycles->{type} ||= 'ticket';
+    }
+
     my %all = (
         '' => [],
         initial => [],
diff --git a/lib/RT/Lifecycle/Ticket.pm b/lib/RT/Lifecycle/Ticket.pm
new file mode 100644
index 0000000..56e0148
--- /dev/null
+++ b/lib/RT/Lifecycle/Ticket.pm
@@ -0,0 +1,116 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+#                                          <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+use strict;
+use warnings;
+
+package RT::Lifecycle::Ticket;
+
+use base qw(RT::Lifecycle);
+
+=head2 Queues
+
+Returns L<RT::Queues> collection with queues that use this lifecycle.
+
+=cut
+
+sub Queues {
+    my $self = shift;
+    require RT::Queues;
+    my $queues = RT::Queues->new( RT->SystemUser );
+    $queues->Limit( FIELD => 'Lifecycle', VALUE => $self->Name );
+    return $queues;
+}
+
+=head3 DefaultOnCreate
+
+Returns the status that should be used by default
+when ticket is created.
+
+=cut
+
+sub DefaultOnCreate {
+    my $self = shift;
+    return $self->DefaultStatus('on_create');
+}
+
+=head3 DefaultOnMerge
+
+Returns the status that should be used when tickets
+are merged.
+
+=cut
+
+sub DefaultOnMerge {
+    my $self = shift;
+    return $self->DefaultStatus('on_merge');
+}
+
+=head3 ReminderStatusOnOpen
+
+Returns the status that should be used when reminders are opened.
+
+=cut
+
+sub ReminderStatusOnOpen {
+    my $self = shift;
+    return $self->DefaultStatus('reminder_on_open') || 'open';
+}
+
+=head3 ReminderStatusOnResolve
+
+Returns the status that should be used when reminders are resolved.
+
+=cut
+
+sub ReminderStatusOnResolve {
+    my $self = shift;
+    return $self->DefaultStatus('reminder_on_resolve') || 'resolved';
+}
+
+1;

commit 53898e86892b261f74e6df92455cd29d696a6399
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Dec 7 21:44:07 2012 -0500

    Minor cleanup of lifecycle tests

diff --git a/t/lifecycles/basics.t b/t/lifecycles/basics.t
index 554c95a..b4828f7 100644
--- a/t/lifecycles/basics.t
+++ b/t/lifecycles/basics.t
@@ -1,7 +1,5 @@
-
 use strict;
 use warnings;
-use Data::Dumper;
 
 BEGIN {require  't/lifecycles/utils.pl'};
 
@@ -244,3 +242,5 @@ diag "'!inactive -> inactive' actions are shown even if ticket has unresolved de
     );
 }
 
+undef $m;
+done_testing;
diff --git a/t/lifecycles/dates.t b/t/lifecycles/dates.t
index 4f613f8..80c24fc 100644
--- a/t/lifecycles/dates.t
+++ b/t/lifecycles/dates.t
@@ -1,7 +1,5 @@
-
 use strict;
 use warnings;
-use Data::Dumper;
 
 BEGIN {require 't/lifecycles/utils.pl'};
 
@@ -23,9 +21,6 @@ my $tstatus = sub {
     return $ticket->Status;
 };
 
-my ($baseurl, $m) = RT::Test->started_ok;
-ok $m->login, 'logged in';
-
 diag "check basic API";
 {
     my $schema = $general->Lifecycle;
@@ -314,3 +309,5 @@ diag "check date changes on moving a ticket";
     ok $ticket->StartedObj->Unix > 0, 'started is set';
     ok $ticket->ResolvedObj->Unix > 0, 'resolved is set';
 }
+
+done_testing;
diff --git a/t/lifecycles/moving.t b/t/lifecycles/moving.t
index 5f184e2..8a03e3e 100644
--- a/t/lifecycles/moving.t
+++ b/t/lifecycles/moving.t
@@ -1,7 +1,5 @@
-
 use strict;
 use warnings;
-use Data::Dumper;
 
 BEGIN {require 't/lifecycles/utils.pl'};
 
@@ -94,3 +92,5 @@ diag "one way map doesn't work backwards";
     is $ticket->Queue, $delivery->id, 'queue is steal the same';
     is $ticket->Status, 'ordered', 'status is steal the same';
 }
+
+done_testing;
diff --git a/t/lifecycles/unresolved-deps.t b/t/lifecycles/unresolved-deps.t
index d195d3b..5da4b8f 100644
--- a/t/lifecycles/unresolved-deps.t
+++ b/t/lifecycles/unresolved-deps.t
@@ -1,8 +1,6 @@
 use strict;
 use warnings;
-use Data::Dumper;
 
-use Test::More tests => 15;
 BEGIN {require  't/lifecycles/utils.pl'};
 
 my $general = RT::Test->load_or_create_queue(
@@ -41,3 +39,5 @@ ok $m->login, 'logged in';
     );
 }
 
+undef $m;
+done_testing;
diff --git a/t/lifecycles/utils.pl b/t/lifecycles/utils.pl
index 3813df3..ec3289f 100644
--- a/t/lifecycles/utils.pl
+++ b/t/lifecycles/utils.pl
@@ -67,6 +67,6 @@ Set(\%Lifecycles,
 END
 }
 
-use RT::Test config => $config;
+use RT::Test config => $config, tests => undef;
 
 1;

commit 71e6b11eabc04cfeca749997de0244bb637e61fe
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Dec 7 21:56:48 2012 -0500

    Split lifecycle status aggregation by type
    
    This ensures that as lifecycles are applied to more than just tickets,
    their aggregated statuses (as determined from ->Load( '' )->Valid) only
    show statuses from lifecycles that could apply to that type of object.

diff --git a/lib/RT/Condition/StatusChange.pm b/lib/RT/Condition/StatusChange.pm
index 667ccee..1de7a8c 100644
--- a/lib/RT/Condition/StatusChange.pm
+++ b/lib/RT/Condition/StatusChange.pm
@@ -114,7 +114,7 @@ sub IsApplicable {
     }
     else {
         $RT::Logger->error("Argument '$argument' is incorrect.")
-            unless RT::Lifecycle->Load('')->IsValid( $argument );
+            unless RT::Lifecycle->Load(Type => 'ticket')->IsValid( $argument );
         return 0;
     }
 
diff --git a/lib/RT/Lifecycle.pm b/lib/RT/Lifecycle.pm
index b66276b..ac522f3 100644
--- a/lib/RT/Lifecycle.pm
+++ b/lib/RT/Lifecycle.pm
@@ -54,16 +54,11 @@ package RT::Lifecycle;
 
 our %LIFECYCLES;
 our %LIFECYCLES_CACHE;
+our %LIFECYCLES_TYPES;
 __PACKAGE__->RegisterRights;
 
 # cache structure:
 #    {
-#        '' => { # all valid statuses
-#            '' => [...],
-#            initial => [...],
-#            active => [...],
-#            inactive => [...],
-#        },
 #        lifecycle_x => {
 #            '' => [...], # all valid in lifecycle
 #            initial => [...],
@@ -119,31 +114,50 @@ sub new {
     return $self;
 }
 
-=head2 Load
+=head2 Load Name => I<NAME>, Type => I<TYPE>
 
-Takes a name of the lifecycle and loads it. If name is empty or undefined then
-loads the global lifecycle with statuses from all named lifecycles.
+Takes a name of the lifecycle and loads it. If only a Type is provided,
+loads the global lifecycle with statuses from all named lifecycles of
+that type.
 
 Can be called as class method, returns a new object, for example:
 
-    my $lifecycle = RT::Lifecycle->Load('default');
+    my $lifecycle = RT::Lifecycle->Load( Name => 'default');
+
+Returns an object which may be a subclass of L<RT::Lifecycle>
+(L<RT::Lifecycle::Ticket>, for example) depending on the type of the
+lifecycle in question.
 
 =cut
 
 sub Load {
     my $self = shift;
-    my $name = shift || '';
-    return $self->new->Load( $name, @_ )
+    return $self->new->Load( @_ )
         unless ref $self;
 
-    return unless exists $LIFECYCLES_CACHE{ $name };
+    unshift @_, Type => "ticket", "Name"
+        if @_ % 2;
 
-    $self->{'name'} = $name;
-    $self->{'data'} = $LIFECYCLES_CACHE{ $name };
+    my %args = (
+        Type => "ticket",
+        Name => '',
+        @_,
+    );
+
+    if (exists $LIFECYCLES_CACHE{ $args{Name} }) {
+        $self->{'name'} = $args{Name};
+        $self->{'data'} = $LIFECYCLES_CACHE{ $args{Name} };
 
-    my $type = $self->{'data'}{'type'} || 'ticket';
-    $type = "RT::Lifecycle::".ucfirst($type);
-    bless $self, $type if $type->require;
+        my $found_type = $self->{'data'}{'type'};
+        warn "Found type of $found_type ne $args{Type}" if $found_type ne $args{Type};
+    } elsif (not $args{Name} and exists $LIFECYCLES_TYPES{ $args{Type} }) {
+        $self->{'data'} = $LIFECYCLES_TYPES{ $args{Type} };
+    } else {
+        return undef;
+    }
+
+    my $class = "RT::Lifecycle::".ucfirst($args{Type});
+    bless $self, $class if $class->require;
 
     return $self;
 }
@@ -161,7 +175,7 @@ sub List {
     $self->FillCache unless keys %LIFECYCLES_CACHE;
 
     return sort grep {$LIFECYCLES_CACHE{$_}{type} eq $for}
-        grep length && $_ ne '__maps__', keys %LIFECYCLES_CACHE;
+        grep $_ ne '__maps__', keys %LIFECYCLES_CACHE;
 }
 
 =head2 Name
@@ -507,7 +521,8 @@ move map from this cycle to provided.
 sub MoveMap {
     my $from = shift; # self
     my $to = shift;
-    $to = RT::Lifecycle->Load( $to ) unless ref $to;
+    my $type = $from->{'data'}{'type'};
+    $to = RT::Lifecycle->Load( Name => $to, Type => $type ) unless ref $to;
     return $LIFECYCLES{'__maps__'}{ $from->Name .' -> '. $to->Name } || {};
 }
 
@@ -535,13 +550,14 @@ move maps.
 
 sub NoMoveMaps {
     my $self = shift;
-    my @list = $self->List;
+    my $type = $self->{'data'}{'type'};
+    my @list = $self->List( $type );
     my @res;
     foreach my $from ( @list ) {
         foreach my $to ( @list ) {
             next if $from eq $to;
             push @res, $from, $to
-                unless RT::Lifecycle->Load( $from )->HasMoveMap( $to );
+                unless RT::Lifecycle->Load( Name => $from, Type => $type )->HasMoveMap( $to );
         }
     }
     return @res;
@@ -562,7 +578,7 @@ sub ForLocalization {
 
     my @res = ();
 
-    push @res, @{ $LIFECYCLES_CACHE{''}{''} || [] };
+    push @res, @{$_->{''}} for values %LIFECYCLES_TYPES;
     foreach my $lifecycle ( values %LIFECYCLES ) {
         push @res,
             grep defined && length,
@@ -587,21 +603,21 @@ sub FillCache {
     %LIFECYCLES_CACHE = %LIFECYCLES = %$map;
     $_ = { %$_ } foreach values %LIFECYCLES_CACHE;
 
-    for my $lifecycles (values %LIFECYCLES_CACHE) {
-        $lifecycles->{type} ||= 'ticket';
-    }
+    for my $lifecycle ( values %LIFECYCLES_CACHE ) {
+        my $type = $lifecycle->{type} ||= 'ticket';
+        $LIFECYCLES_TYPES{$type} ||= {
+            '' => [],
+            initial => [],
+            active => [],
+            inactive => [],
+            actions => [],
+        };
 
-    my %all = (
-        '' => [],
-        initial => [],
-        active => [],
-        inactive => [],
-    );
-    foreach my $lifecycle ( values %LIFECYCLES_CACHE ) {
         my @res;
-        foreach my $type ( qw(initial active inactive) ) {
-            push @{ $all{ $type } }, @{ $lifecycle->{ $type } || [] };
-            push @res,               @{ $lifecycle->{ $type } || [] };
+        foreach my $category ( qw(initial active inactive) ) {
+            my @vals = @{ $lifecycle->{ $category } ||= [] };
+            push @{ $LIFECYCLES_TYPES{$type}{$category} }, @vals;
+            push @res,                                     @vals;
         }
 
         my %seen;
@@ -612,12 +628,15 @@ sub FillCache {
             $lifecycle->{'transitions'}{''} = [ grep $_ ne 'deleted', @res ];
         }
     }
-    foreach my $type ( qw(initial active inactive), '' ) {
-        my %seen;
-        @{ $all{ $type } } = grep !$seen{ lc $_ }++, @{ $all{ $type } };
-        push @{ $all{''} }, @{ $all{ $type } } if $type;
+    for my $type (keys %LIFECYCLES_TYPES) {
+        for my $category ( qw(initial active inactive), '' ) {
+            my %seen;
+            @{ $LIFECYCLES_TYPES{$type}{$category} } =
+                grep !$seen{ lc $_ }++, @{ $LIFECYCLES_TYPES{$type}{$category} };
+            push @{ $LIFECYCLES_TYPES{$type}{''} },
+                @{ $LIFECYCLES_TYPES{$type}{$category} } if $category;
+        }
     }
-    $LIFECYCLES_CACHE{''} = \%all;
 
     foreach my $lifecycle ( values %LIFECYCLES_CACHE ) {
         my @res;
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 2bc8f20..b161411 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -243,17 +243,17 @@ sub RightCategories {
 
 sub Lifecycle {
     my $self = shift;
-    unless (ref $self && $self->id) { 
-        return RT::Lifecycle->Load('')
+    unless (ref $self && $self->id) {
+        return RT::Lifecycle->Load( Type => 'ticket')
     }
 
     my $name = $self->_Value( Lifecycle => @_ );
     $name ||= 'default';
 
-    my $res = RT::Lifecycle->Load( $name );
+    my $res = RT::Lifecycle->Load( Name => $name );
     unless ( $res ) {
         $RT::Logger->error("Lifecycle '$name' for queue '".$self->Name."' doesn't exist");
-        return RT::Lifecycle->Load('default');
+        return RT::Lifecycle->Load( Name => 'default');
     }
     return $res;
 }
@@ -278,7 +278,7 @@ lifecycle is configured. Returns undef otherwise.
 sub ValidateLifecycle {
     my $self = shift;
     my $value = shift;
-    return undef unless RT::Lifecycle->Load( $value );
+    return undef unless RT::Lifecycle->Load( Name => $value );
     return 1;
 }
 
diff --git a/share/html/Elements/QueueSummaryByLifecycle b/share/html/Elements/QueueSummaryByLifecycle
index 1410e82..79e3a59 100644
--- a/share/html/Elements/QueueSummaryByLifecycle
+++ b/share/html/Elements/QueueSummaryByLifecycle
@@ -106,7 +106,7 @@ $m->callback( CallbackName => 'Filter', Queues => \@queues );
 my %lifecycle;
 
 for my $queue (@queues) {
-    my $cycle = RT::Lifecycle->Load( $queue->{'Lifecycle'} );
+    my $cycle = RT::Lifecycle->Load( Name => $queue->{'Lifecycle'} );
     $lifecycle{ lc $cycle->Name } = $cycle;
 }
 
diff --git a/share/html/Elements/QueueSummaryByStatus b/share/html/Elements/QueueSummaryByStatus
index f649d28..cd8b277 100644
--- a/share/html/Elements/QueueSummaryByStatus
+++ b/share/html/Elements/QueueSummaryByStatus
@@ -104,7 +104,7 @@ $m->callback( CallbackName => 'Filter', Queues => \@queues );
 my %lifecycle;
 
 for my $queue (@queues) {
-    my $cycle = RT::Lifecycle->Load( $queue->{'Lifecycle'} );
+    my $cycle = RT::Lifecycle->Load( Name => $queue->{'Lifecycle'} );
     $lifecycle{ lc $cycle->Name } = $cycle;
 }
 
diff --git a/t/lifecycles/types.t b/t/lifecycles/types.t
new file mode 100644
index 0000000..83fe06e
--- /dev/null
+++ b/t/lifecycles/types.t
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+BEGIN {require  't/lifecycles/utils.pl'};
+
+is_deeply( [ RT::Lifecycle->List], [qw/ approvals default delivery /],
+       "Get the list of lifecycles (implicitly for for tickets)");
+is_deeply( [ RT::Lifecycle->List('ticket') ],  [qw/ approvals default delivery /],
+       "Get the list of lifecycles for tickets");
+is_deeply( [ RT::Lifecycle->List('racecar') ], [qw/ racing /],
+       "Get the list of lifecycles for other types");
+
+my $tickets = RT::Lifecycle->Load( Name => '', Type => 'ticket' );
+ok($tickets, "Got a generalized lifecycle for tickets");
+isa_ok( $tickets, "RT::Lifecycle::Ticket", "Is the right subclass" );
+is_deeply( [ sort $tickets->Valid ],
+           [ sort (qw(new open stalled resolved rejected deleted ordered),
+             'on way', 'delayed', 'delivered') ],
+           "Only gets ticket statuses" );
+
+
+my $racecars = RT::Lifecycle->Load( Name => '', Type => 'racecar' );
+ok($racecars, "Got a generalized lifecycle for racecars");
+isa_ok( $racecars, "RT::Lifecycle", "Is the generalized subclass" );
+is_deeply( [ sort $racecars->Valid ],
+           [ sort ('on-your-mark', 'get-set', 'go', 'first', 'second', 'third', 'no-place') ],
+           "Only gets racecar statuses" );
+
+done_testing;
diff --git a/t/lifecycles/utils.pl b/t/lifecycles/utils.pl
index ec3289f..4dbba23 100644
--- a/t/lifecycles/utils.pl
+++ b/t/lifecycles/utils.pl
@@ -63,6 +63,11 @@ Set(\%Lifecycles,
             'delayed -> on way'   => {label => 'Put On Way', update => 'Respond'},
         },
     },
+    racing => {
+        type => 'racecar',
+        active => ['on-your-mark', 'get-set', 'go'],
+        inactive => ['first', 'second', 'third', 'no-place'],
+    },
 );
 END
 }

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


More information about the Rt-commit mailing list