rt 4.0.23
[freeside.git] / rt / lib / RT / Condition / StatusChange.pm
index b20a5ac..668c5bc 100644 (file)
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
 package RT::Condition::StatusChange;
 use base 'RT::Condition';
 use strict;
+use warnings;
 
+=head2 DESCRIPTION
 
-=head2 IsApplicable
+This condition check passes if the current transaction is a status change.
 
-If the argument passed in is equivalent to the new value of
-the Status Obj
+The argument can be used to apply additional conditions on old and new values.
+
+If argument is empty then the check passes for any change of the status field.
+
+If argument is equal to new value then check is passed. This is behavior
+is close to RT 3.8 and older. For example, setting the argument to 'resolved' means
+'fire scrip when status changed from any to resolved'.
+
+The following extended format is supported:
+
+    old: comma separated list; new: comma separated list
+
+For example:
+
+    old: open; new: resolved
+
+You can omit old or new part, for example:
+
+    old: open
+
+    new: resolved
+
+You can specify multiple values, for example:
+
+    old: new, open; new: resolved, rejected
+
+Status sets ('initial', 'active' or 'inactive') can be used, for example:
+
+    old: active; new: inactive
+
+    old: initial, active; new: resolved
 
 =cut
 
 sub IsApplicable {
     my $self = shift;
-    if (($self->TransactionObj->Field eq 'Status') and 
-    ($self->Argument eq $self->TransactionObj->NewValue())) {
-       return(1);
-    } 
+    my $txn = $self->TransactionObj;
+    my ($type, $field) = ($txn->Type, $txn->Field);
+    return 0 unless $type eq 'Status' || ($type eq 'Set' && $field eq 'Status');
+
+    my $argument = $self->Argument;
+    return 1 unless $argument;
+
+    my $new = $txn->NewValue || '';
+    return 1 if $argument eq $new;
+
+    # let's parse argument
+    my ($old_must_be, $new_must_be) = ('', '');
+    if ( $argument =~ /^\s*old:\s*(.*);\s*new:\s*(.*)\s*$/i ) {
+        ($old_must_be, $new_must_be) = ($1, $2);
+    }
+    elsif ( $argument =~ /^\s*new:\s*(.*)\s*$/i ) {
+        $new_must_be = $1;
+    }
+    elsif ( $argument =~ /^\s*old:\s*(.*)\s*$/i ) {
+        $old_must_be = $1;
+    }
     else {
-       return(undef);
+        $RT::Logger->error("Argument '$argument' is incorrect.")
+            unless RT::Lifecycle->Load('')->IsValid( $argument );
+        return 0;
+    }
+
+    my $lifecycle = $self->TicketObj->QueueObj->Lifecycle;
+    if ( $new_must_be ) {
+        return 0 unless grep lc($new) eq lc($_),
+            map {m/^(initial|active|inactive)$/i? $lifecycle->Valid(lc $_): $_ }
+            grep defined && length,
+            map { s/^\s+//; s/\s+$//; $_ }
+            split /,/, $new_must_be;
+    }
+    if ( $old_must_be ) {
+        my $old = lc($txn->OldValue || '');
+        return 0 unless grep $old eq lc($_),
+            map {m/^(initial|active|inactive)$/i? $lifecycle->Valid(lc $_): $_ }
+            grep defined && length,
+            map { s/^\s+//; s/\s+$//; $_ }
+            split /,/, $old_must_be;
     }
+    return 1;
 }
 
 RT::Base->_ImportOverlays();