import rt 3.2.2
[freeside.git] / rt / lib / RT / Transaction_Overlay.pm
index 54bb326..17e47cb 100644 (file)
@@ -1,8 +1,14 @@
-# BEGIN LICENSE BLOCK
+# {{{ BEGIN BPS TAGGED BLOCK
 # 
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#  
+# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
+#                                          <jesse@bestpractical.com>
 # 
-# (Except where explictly superceded by other copyright notices)
+# (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
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
 # 
-# Unless otherwise specified, all modifications, corrections or
-# extensions to this work which alter its source code become the
-# property of Best Practical Solutions, LLC when submitted for
-# inclusion in the work.
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# 
+# 
+# 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.)
 # 
-# END LICENSE BLOCK
+# 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
 =head1 NAME
 
   RT::Transaction - RT\'s transaction object
@@ -51,7 +73,10 @@ ok(require RT::Transaction);
 use strict;
 no warnings qw(redefine);
 
+use vars qw( %_BriefDescriptions );
+
 use RT::Attachments;
+use RT::Scrips;
 
 # {{{ sub Create 
 
@@ -80,6 +105,7 @@ sub Create {
         NewValue       => undef,
         MIMEObj        => undef,
         ActivateScrips => 1,
+        CommitScrips => 1,
         @_
     );
 
@@ -107,77 +133,48 @@ sub Create {
  
     my $id = $self->SUPER::Create(%params);
     $self->Load($id);
-    $self->_Attach( $args{'MIMEObj'} )
-      if defined $args{'MIMEObj'};
+    $self->_Attach( $args{'MIMEObj'} ) if defined $args{'MIMEObj'};
+
 
     #Provide a way to turn off scrips if we need to
+        $RT::Logger->debug('About to think about scrips for transaction' .$self->Id);            
     if ( $args{'ActivateScrips'} ) {
+       $self->{'scrips'} = RT::Scrips->new($RT::SystemUser);
 
-        #We're really going to need a non-acled ticket for the scrips to work
-        my $TicketAsSystem = RT::Ticket->new($RT::SystemUser);
-        $TicketAsSystem->Load( $args{'Ticket'} )
-          || $RT::Logger->err("$self couldn't load ticket $args{'Ticket'}\n");
-
-        my $TransAsSystem = RT::Transaction->new($RT::SystemUser);
-        $TransAsSystem->Load( $self->id )
-          || $RT::Logger->err(
-            "$self couldn't load a copy of itself as superuser\n"); 
-        # {{{ Deal with Scrips
-
-        use RT::Scrips;
-        my $PossibleScrips = RT::Scrips->new($RT::SystemUser);
-
-        $PossibleScrips->LimitToQueue( $TicketAsSystem->QueueObj->Id )
-          ;                                  #Limit it to  $Ticket->QueueObj->Id
-        $PossibleScrips->LimitToGlobal()
-           unless $TicketAsSystem->QueueObj->Disabled;    # or to "global"
-
-
-        $PossibleScrips->Limit(FIELD => "Stage", VALUE => "TransactionCreate");
-
+        $RT::Logger->debug('About to prepare scrips for transaction' .$self->Id);            
 
-        my $ConditionsAlias = $PossibleScrips->NewAlias('ScripConditions');
-
-        $PossibleScrips->Join(
-            ALIAS1 => 'main',
-            FIELD1 => 'ScripCondition',
-            ALIAS2 => $ConditionsAlias,
-            FIELD2 => 'id'
+        $self->{'scrips'}->Prepare(
+            Stage       => 'TransactionCreate',
+            Type        => $args{'Type'},
+            Ticket      => $args{'Ticket'},
+            Transaction => $self->id,
         );
+        if ($args{'CommitScrips'} ) {
+            $RT::Logger->debug('About to commit scrips for transaction' .$self->Id);
+            $self->{'scrips'}->Commit();
+        }
+    }
 
-        #We only want things where the scrip applies to this sort of transaction
-        $PossibleScrips->Limit(
-            ALIAS           => $ConditionsAlias,
-            FIELD           => 'ApplicableTransTypes',
-            OPERATOR        => 'LIKE',
-            VALUE           => $args{'Type'},
-            ENTRYAGGREGATOR => 'OR',
-        );
+    return ( $id, $self->loc("Transaction Created") );
+}
 
-        # Or where the scrip applies to any transaction
-        $PossibleScrips->Limit(
-            ALIAS           => $ConditionsAlias,
-            FIELD           => 'ApplicableTransTypes',
-            OPERATOR        => 'LIKE',
-            VALUE           => "Any",
-            ENTRYAGGREGATOR => 'OR',
-        );
+# }}}
 
-        #Iterate through each script and check it's applicability.
+=head2 Scrips
 
-        while ( my $Scrip = $PossibleScrips->Next() ) {
-            $Scrip->Apply (TicketObj => $TicketAsSystem,
-                           TransactionObj => $TransAsSystem);
-        }
+Returns the Scrips object for this transaction.
+This routine is only useful on a freshly created transaction object.
+Scrips do not get persisted to the database with transactions.
 
-        # }}}
 
-    }
+=cut
 
-    return ( $id, $self->loc("Transaction Created") );
+
+sub Scrips {
+    my $self = shift;
+    return($self->{'scrips'});
 }
 
-# }}}
 
 # {{{ sub Delete
 
@@ -254,7 +251,7 @@ sub Content {
     if ( $args{'Quote'} ) {
 
         # Remove quoted signature.
-        $content =~ s/\n-- \n(.*)$//s;
+        $content =~ s/\n-- \n(.*?)$//s;
 
         # What's the longest line like?
         my $max = 0;
@@ -460,8 +457,10 @@ sub Description {
     my $self = shift;
 
     #Check those ACLs
-    #If it's a comment, we need to be extra special careful
-    if ( $self->__Value('Type') eq 'Comment' ) {
+    #If it's a comment or a comment email record,
+    #  we need to be extra special careful
+
+    if ( $self->__Value('Type') =~ /^Comment/ ) {
         unless ( $self->CurrentUserHasRight('ShowTicketComments') ) {
             return ( $self->loc("Permission Denied") );
         }
@@ -495,9 +494,9 @@ sub BriefDescription {
     my $self = shift;
 
 
-    #Check those ACLs
-    #If it's a comment, we need to be extra special careful
-    if ( $self->__Value('Type') eq 'Comment' ) {
+    #If it's a comment or a comment email record,
+    #  we need to be extra special careful
+    if ( $self->__Value('Type') =~ /^Comment/ ) {
         unless ( $self->CurrentUserHasRight('ShowTicketComments') ) {
             return ( $self->loc("Permission Denied") );
         }
@@ -535,16 +534,32 @@ sub BriefDescription {
         return ( $self->loc( "[_1] changed from [_2] to [_3]", $self->Field , ( $self->OldValue || $no_value ) ,  $self->NewValue ));
     }
 
-    if ( $type eq 'Correspond' ) {
-        return $self->loc("Correspondence added");
-    }
-
-    elsif ( $type eq 'Comment' ) {
-        return $self->loc("Comments added");
+    if (my $code = $_BriefDescriptions{$type}) {
+        return $code->($self);
     }
 
-    elsif ( $type eq 'CustomField' ) {
+    return $self->loc( "Default: [_1]/[_2] changed from [_3] to [_4]", $type, $self->Field, $self->OldValue, $self->NewValue );
+}
 
+%_BriefDescriptions = (
+    CommentEmailRecord => sub {
+        my $self = shift;
+        return $self->loc("Outgoing email about a comment recorded");
+    },
+    EmailRecord => sub {
+        my $self = shift;
+        return $self->loc("Outgoing email recorded");
+    },
+    Correspond => sub {
+        my $self = shift;
+        return $self->loc("Correspondence added");
+    },
+    Comment => sub {
+        my $self = shift;
+        return $self->loc("Comments added");
+    },
+    CustomField => sub {
+        my $self = shift;
         my $field = $self->loc('CustomField');
 
         if ( $self->Field ) {
@@ -563,110 +578,130 @@ sub BriefDescription {
         else {
             return $self->loc("[_1] [_2] changed to [_3]", $field, $self->OldValue, $self->NewValue );
         }
-    }
-
-    elsif ( $type eq 'Untake' ) {
+    },
+    Untake => sub {
+        my $self = shift;
         return $self->loc("Untaken");
-    }
-
-    elsif ( $type eq "Take" ) {
+    },
+    Take => sub {
+        my $self = shift;
         return $self->loc("Taken");
-    }
-
-    elsif ( $type eq "Force" ) {
+    },
+    Force => sub {
+        my $self = shift;
         my $Old = RT::User->new( $self->CurrentUser );
         $Old->Load( $self->OldValue );
         my $New = RT::User->new( $self->CurrentUser );
         $New->Load( $self->NewValue );
 
         return $self->loc("Owner forcibly changed from [_1] to [_2]" , $Old->Name , $New->Name);
-    }
-    elsif ( $type eq "Steal" ) {
+    },
+    Steal => sub {
+        my $self = shift;
         my $Old = RT::User->new( $self->CurrentUser );
         $Old->Load( $self->OldValue );
         return $self->loc("Stolen from [_1] ",  $Old->Name);
-    }
-
-    elsif ( $type eq "Give" ) {
+    },
+    Give => sub {
+        my $self = shift;
         my $New = RT::User->new( $self->CurrentUser );
         $New->Load( $self->NewValue );
         return $self->loc( "Given to [_1]",  $New->Name );
-    }
-
-    elsif ( $type eq 'AddWatcher' ) {
+    },
+    AddWatcher => sub {
+        my $self = shift;
         my $principal = RT::Principal->new($self->CurrentUser);
         $principal->Load($self->NewValue);
         return $self->loc( "[_1] [_2] added", $self->Field, $principal->Object->Name);
-    }
-
-    elsif ( $type eq 'DelWatcher' ) {
+    },
+    DelWatcher => sub {
+        my $self = shift;
         my $principal = RT::Principal->new($self->CurrentUser);
         $principal->Load($self->OldValue);
         return $self->loc( "[_1] [_2] deleted", $self->Field, $principal->Object->Name);
-    }
-
-    elsif ( $type eq 'Subject' ) {
+    },
+    Subject => sub {
+        my $self = shift;
         return $self->loc( "Subject changed to [_1]", $self->Data );
-    }
+    },
+    AddLink => sub {
+        my $self = shift;
+        my $value;
+        if ( $self->NewValue ) {
+            my $URI = RT::URI->new( $self->CurrentUser );
+            $URI->FromURI( $self->NewValue );
+            if ( $URI->Resolver ) {
+                $value = $URI->Resolver->AsString;
+            }
+            else {
+                $value = $self->NewValue;
+            }
+            if ( $self->Field eq 'DependsOn' ) {
+                return $self->loc( "Dependency on [_1] added", $value );
+            }
+            elsif ( $self->Field eq 'DependedOnBy' ) {
+                return $self->loc( "Dependency by [_1] added", $value );
 
-    elsif ( $type eq 'AddLink' ) {
+            }
+            elsif ( $self->Field eq 'RefersTo' ) {
+                return $self->loc( "Reference to [_1] added", $value );
+            }
+            elsif ( $self->Field eq 'ReferredToBy' ) {
+                return $self->loc( "Reference by [_1] added", $value );
+            }
+            elsif ( $self->Field eq 'MemberOf' ) {
+                return $self->loc( "Membership in [_1] added", $value );
+            }
+            elsif ( $self->Field eq 'HasMember' ) {
+                return $self->loc( "Member [_1] added", $value );
+            }
+            elsif ( $self->Field eq 'MergedInto' ) {
+                return $self->loc( "Merged into [_1]", $value );
+            }
+        }
+        else {
+            return ( $self->Data );
+        }
+    },
+    DeleteLink => sub {
+        my $self = shift;
         my $value;
-       if ($self->NewValue) {
-               my $URI = RT::URI->new($self->CurrentUser);
-               $URI->FromURI($self->NewValue);
-               if ($URI->Resolver) {
-                       $value = $URI->Resolver->AsString;
-               } else {
-                       $value = $self->NewValue;
-               }
-       }
-       if ($self->Field eq 'DependsOn') {
-               return $self->loc("Dependency on [_1] added",$value);
-       } elsif ($self->Field eq 'DependedOnBy') {
-               return $self->loc("Dependency by [_1] added",$value);
-               
-       } elsif ($self->Field eq 'RefersTo') {
-               return $self->loc("Reference to [_1] added",$value);
-       } elsif ($self->Field eq 'ReferredToBy') {
-               return $self->loc("Reference by [_1] added",$value);
-       } elsif ($self->Field eq 'MemberOf') {
-               return $self->loc("Membership in [_1] added",$value);
-       } elsif ($self->Field eq 'HasMember') {
-               return $self->loc("Member [_1] added",$value);
-       } else {
-        return ( $self->Data );
-       }
-    }
-    elsif ( $type eq 'DeleteLink' ) {
-    my $value;
-       if ($self->OldValue) {
-               my $URI = RT::URI->new($self->CurrentUser);
-               $URI->FromURI($self->OldValue);
-               if ($URI->Resolver) {
-                       $value = $URI->Resolver->AsString;
-               } else {
-                       $value = $self->OldValue;
-               }
-       }
-
-       if ($self->Field eq 'DependsOn') {
-               return $self->loc("Dependency on [_1] deleted",$value);
-       } elsif ($self->Field eq 'DependedOnBy') {
-               return $self->loc("Dependency by [_1] deleted",$value);
-               
-       } elsif ($self->Field eq 'RefersTo') {
-               return $self->loc("Reference to [_1] deleted",$value);
-       } elsif ($self->Field eq 'ReferredToBy') {
-               return $self->loc("Reference by [_1] deleted",$value);
-       } elsif ($self->Field eq 'MemberOf') {
-               return $self->loc("Membership in [_1] deleted",$value);
-       } elsif ($self->Field eq 'HasMember') {
-               return $self->loc("Member [_1] deleted",$value);
-       } else {
-        return ( $self->Data );
-       }
-    }
-    elsif ( $type eq 'Set' ) {
+        if ( $self->OldValue ) {
+            my $URI = RT::URI->new( $self->CurrentUser );
+            $URI->FromURI( $self->OldValue );
+            if ( $URI->Resolver ) {
+                $value = $URI->Resolver->AsString;
+            }
+            else {
+                $value = $self->OldValue;
+            }
+
+            if ( $self->Field eq 'DependsOn' ) {
+                return $self->loc( "Dependency on [_1] deleted", $value );
+            }
+            elsif ( $self->Field eq 'DependedOnBy' ) {
+                return $self->loc( "Dependency by [_1] deleted", $value );
+
+            }
+            elsif ( $self->Field eq 'RefersTo' ) {
+                return $self->loc( "Reference to [_1] deleted", $value );
+            }
+            elsif ( $self->Field eq 'ReferredToBy' ) {
+                return $self->loc( "Reference by [_1] deleted", $value );
+            }
+            elsif ( $self->Field eq 'MemberOf' ) {
+                return $self->loc( "Membership in [_1] deleted", $value );
+            }
+            elsif ( $self->Field eq 'HasMember' ) {
+                return $self->loc( "Member [_1] deleted", $value );
+            }
+        }
+        else {
+            return ( $self->Data );
+        }
+    },
+    Set => sub {
+        my $self = shift;
         if ( $self->Field eq 'Queue' ) {
             my $q1 = new RT::Queue( $self->CurrentUser );
             $q1->Load( $self->OldValue );
@@ -676,25 +711,22 @@ sub BriefDescription {
         }
 
         # Write the date/time change at local time:
-    elsif ($self->Field =~  /Due|Starts|Started|Told/) {
-        my $t1 = new RT::Date($self->CurrentUser);
-        $t1->Set(Format => 'ISO', Value => $self->NewValue);
-        my $t2 = new RT::Date($self->CurrentUser);
-        $t2->Set(Format => 'ISO', Value => $self->OldValue);
-        return $self->loc( "[_1] changed from [_2] to [_3]", $self->Field, $t2->AsString, $t1->AsString );
-    }
+        elsif ($self->Field =~  /Due|Starts|Started|Told/) {
+            my $t1 = new RT::Date($self->CurrentUser);
+            $t1->Set(Format => 'ISO', Value => $self->NewValue);
+            my $t2 = new RT::Date($self->CurrentUser);
+            $t2->Set(Format => 'ISO', Value => $self->OldValue);
+            return $self->loc( "[_1] changed from [_2] to [_3]", $self->Field, $t2->AsString, $t1->AsString );
+        }
         else {
             return $self->loc( "[_1] changed from [_2] to [_3]", $self->Field, $self->OldValue, $self->NewValue );
         }
-    }
-    elsif ( $type eq 'PurgeTransaction' ) {
+    },
+    PurgeTransaction => sub {
+        my $self = shift;
         return $self->loc("Transaction [_1] purged", $self->Data);
-    }
-    else {
-        return $self->loc( "Default: [_1]/[_2] changed from [_3] to [_4]", $type, $self->Field, $self->OldValue, $self->NewValue );
-
-    }
-}
+    },
+);
 
 # }}}
 
@@ -778,6 +810,19 @@ sub _Value {
             return (undef);
         }
     }
+    elsif ( $self->__Value('Type') eq 'CommentEmailRecord' ) {
+        unless ( $self->CurrentUserHasRight('ShowTicketComments')
+            && $self->CurrentUserHasRight('ShowOutgoingEmail') ) {
+            return (undef);
+        }
+
+    }
+    elsif ( $self->__Value('Type') eq 'EmailRecord' ) {
+        unless ( $self->CurrentUserHasRight('ShowOutgoingEmail')) {
+            return (undef);
+        }
+
+    }
 
     #if they ain't got rights to see, don't let em
     else {
@@ -814,4 +859,12 @@ sub CurrentUserHasRight {
 
 # }}}
 
+# Transactions don't change. by adding this cache congif directiove, we don't lose pathalogically on long tickets.
+sub _CacheConfig {
+  {
+     'cache_p'        => 1,
+     'fast_update_p'  => 1,
+     'cache_for_sec'  => 6000,
+  }
+}
 1;