-# 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
use strict;
no warnings qw(redefine);
+use vars qw( %_BriefDescriptions );
+
use RT::Attachments;
+use RT::Scrips;
# {{{ sub Create
NewValue => undef,
MIMEObj => undef,
ActivateScrips => 1,
+ CommitScrips => 1,
@_
);
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
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;
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") );
}
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") );
}
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 ) {
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 );
}
# 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 );
-
- }
-}
+ },
+);
# }}}
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 {
# }}}
+# 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;