summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Scrip_Overlay.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Scrip_Overlay.pm')
-rw-r--r--rt/lib/RT/Scrip_Overlay.pm365
1 files changed, 228 insertions, 137 deletions
diff --git a/rt/lib/RT/Scrip_Overlay.pm b/rt/lib/RT/Scrip_Overlay.pm
index 79499fc82..1e1854a00 100644
--- a/rt/lib/RT/Scrip_Overlay.pm
+++ b/rt/lib/RT/Scrip_Overlay.pm
@@ -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
@@ -14,13 +20,29 @@
# 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::Scrip - an RT Scrip object
@@ -79,8 +101,7 @@ ok ($ticket2->Priority != '87', "Ticket priority is set right");
use strict;
no warnings qw(redefine);
-
-# {{{ sub Create
+# {{{ sub Create
=head2 Create
@@ -107,24 +128,24 @@ sub Create {
my $self = shift;
my %args = (
Queue => 0,
- Template => 0, # name or id
- ScripAction => 0, # name or id
- ScripCondition => 0, # name or id
+ Template => 0, # name or id
+ ScripAction => 0, # name or id
+ ScripCondition => 0, # name or id
Stage => 'TransactionCreate',
Description => undef,
CustomPrepareCode => undef,
CustomCommitCode => undef,
CustomIsApplicableCode => undef,
- @_
- );
+ @_ );
-
- if (! $args{'Queue'} ) {
- unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'ModifyScrips') ) {
+ if ( !$args{'Queue'} ) {
+ unless ( $self->CurrentUser->HasRight( Object => $RT::System,
+ Right => 'ModifyScrips' )
+ ) {
return ( 0, $self->loc('Permission Denied') );
}
- $args{'Queue'} = 0; # avoid undef sneaking in
+ $args{'Queue'} = 0; # avoid undef sneaking in
}
else {
my $QueueObj = new RT::Queue( $self->CurrentUser );
@@ -138,33 +159,33 @@ sub Create {
$args{'Queue'} = $QueueObj->id();
}
- #TODO +++ validate input
+ #TODO +++ validate input
require RT::ScripAction;
my $action = new RT::ScripAction( $self->CurrentUser );
- if ($args{'ScripAction'}) {
- $action->Load( $args{'ScripAction'});
+ if ( $args{'ScripAction'} ) {
+ $action->Load( $args{'ScripAction'} );
}
return ( 0, $self->loc( "Action [_1] not found", $args{'ScripAction'} ) )
unless $action->Id;
require RT::Template;
my $template = new RT::Template( $self->CurrentUser );
- if ($args{'Template'} ) {
- $template->Load( $args{'Template'});
+ if ( $args{'Template'} ) {
+ $template->Load( $args{'Template'} );
}
return ( 0, $self->loc('Template not found') ) unless $template->Id;
require RT::ScripCondition;
my $condition = new RT::ScripCondition( $self->CurrentUser );
- if ($args{'ScripCondition'} ) {
+ if ( $args{'ScripCondition'} ) {
$condition->Load( $args{'ScripCondition'} );
}
unless ( $condition->Id ) {
return ( 0, $self->loc('Condition not found') );
}
- my ($id,$msg) = $self->SUPER::Create(
+ my ( $id, $msg ) = $self->SUPER::Create(
Queue => $args{'Queue'},
Template => $template->Id,
ScripCondition => $condition->id,
@@ -180,7 +201,7 @@ sub Create {
return ( $id, $self->loc('Scrip Created') );
}
else {
- return($id,$msg);
+ return ( $id, $msg );
}
}
@@ -196,13 +217,14 @@ Delete this object
sub Delete {
my $self = shift;
-
- unless ($self->CurrentUserHasRight('ModifyScrips')) {
- return (0, $self->loc('Permission Denied'));
+
+ unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
+ return ( 0, $self->loc('Permission Denied') );
}
-
- return ($self->SUPER::Delete(@_));
+
+ return ( $self->SUPER::Delete(@_) );
}
+
# }}}
# {{{ sub QueueObj
@@ -215,20 +237,19 @@ Retuns an RT::Queue object with this Scrip\'s queue
sub QueueObj {
my $self = shift;
-
- if (!$self->{'QueueObj'}) {
- require RT::Queue;
- $self->{'QueueObj'} = RT::Queue->new($self->CurrentUser);
- $self->{'QueueObj'}->Load($self->__Value('Queue'));
+
+ if ( !$self->{'QueueObj'} ) {
+ require RT::Queue;
+ $self->{'QueueObj'} = RT::Queue->new( $self->CurrentUser );
+ $self->{'QueueObj'}->Load( $self->__Value('Queue') );
}
- return ($self->{'QueueObj'});
+ return ( $self->{'QueueObj'} );
}
# }}}
# {{{ sub ActionObj
-
=head2 ActionObj
Retuns an RT::Action object with this Scrip\'s Action
@@ -237,16 +258,17 @@ Retuns an RT::Action object with this Scrip\'s Action
sub ActionObj {
my $self = shift;
-
- unless (defined $self->{'ScripActionObj'}) {
- require RT::ScripAction;
-
- $self->{'ScripActionObj'} = RT::ScripAction->new($self->CurrentUser);
- #TODO: why are we loading Actions with templates like this.
- # two separate methods might make more sense
- $self->{'ScripActionObj'}->Load($self->ScripAction, $self->Template);
+
+ unless ( defined $self->{'ScripActionObj'} ) {
+ require RT::ScripAction;
+
+ $self->{'ScripActionObj'} = RT::ScripAction->new( $self->CurrentUser );
+
+ #TODO: why are we loading Actions with templates like this.
+ # two seperate methods might make more sense
+ $self->{'ScripActionObj'}->Load( $self->ScripAction, $self->Template );
}
- return ($self->{'ScripActionObj'});
+ return ( $self->{'ScripActionObj'} );
}
# }}}
@@ -276,6 +298,7 @@ sub ConditionObj {
# }}}
# {{{ sub TemplateObj
+
=head2 TemplateObj
Retuns an RT::Template object with this Scrip\'s Template
@@ -284,20 +307,21 @@ Retuns an RT::Template object with this Scrip\'s Template
sub TemplateObj {
my $self = shift;
-
- unless (defined $self->{'TemplateObj'}) {
- require RT::Template;
- $self->{'TemplateObj'} = RT::Template->new($self->CurrentUser);
- $self->{'TemplateObj'}->Load($self->Template);
+
+ unless ( defined $self->{'TemplateObj'} ) {
+ require RT::Template;
+ $self->{'TemplateObj'} = RT::Template->new( $self->CurrentUser );
+ $self->{'TemplateObj'}->Load( $self->Template );
}
- return ($self->{'TemplateObj'});
+ return ( $self->{'TemplateObj'} );
}
# }}}
-
# {{{ Dealing with this instance of a scrip
+# {{{ sub Apply
+
=head2 Apply { TicketObj => undef, TransactionObj => undef}
This method instantiates the ScripCondition and ScripAction objects for a
@@ -312,66 +336,44 @@ should be loaded by the SuperUser role
=cut
-# {{{ sub Apply
-
sub Apply {
my $self = shift;
my %args = ( TicketObj => undef,
TransactionObj => undef,
@_ );
- # We want to make sure that if a scrip dies, we don't get
- # hurt
- eval {
-
- #Load the scrip's Condition object
- $self->ConditionObj->LoadCondition(
- ScripObj => $self,
- TicketObj => $args{'TicketObj'},
- TransactionObj => $args{'TransactionObj'},
- );
+ $RT::Logger->debug("Now applying scrip ".$self->Id . " for transaction ".$args{'TransactionObj'}->id);
- unless ( $self->IsApplicable() ) {
- $self->ConditionObj->DESTROY;
- return (undef);
- }
-
- #If it's applicable, prepare and commit it
- $self->ActionObj->LoadAction( ScripObj => $self,
- TicketObj => $args{'TicketObj'},
- TransactionObj => $args{'TransactionObj'},
- );
+ my $ApplicableTransactionObj = $self->IsApplicable( TicketObj => $args{'TicketObj'},
+ TransactionObj => $args{'TransactionObj'} );
+ unless ( $ApplicableTransactionObj ) {
+ return undef;
+ }
- unless ( $self->Prepare() ) {
- $RT::Logger->info(
- "$self: Couldn't prepare " . $self->ActionObj->Name );
- $self->ActionObj->DESTROY();
- $self->ConditionObj->DESTROY();
- return (undef);
- }
- unless ( $self->Commit() ) {
- $RT::Logger->info(
- "$self: Couldn't commit " . $self->ActionObj->Name );
- $self->ActionObj->DESTROY();
- $self->ConditionObj->DESTROY();
- return (undef);
- }
+ if ( $ApplicableTransactionObj->id != $args{'TransactionObj'}->id ) {
+ $RT::Logger->debug("Found an applicable transaction ".$ApplicableTransactionObj->Id . " in the same batch with transaction ".$args{'TransactionObj'}->id);
+ }
- #Searchbuilder caching isn't perfectly coherent. got to reload the ticket object, since it
- # may have changed
- $args{'TicketObj'}->Load($args{'TicketObj'}->Id);
+ #If it's applicable, prepare and commit it
+ $RT::Logger->debug("Now preparing scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
+ unless ( $self->Prepare( TicketObj => $args{'TicketObj'},
+ TransactionObj => $ApplicableTransactionObj )
+ ) {
+ return undef;
+ }
- #We're done with it. lets clean up.
- #TODO: something else isn't letting these get garbage collected. check em out.
- $self->ActionObj->DESTROY();
- $self->ConditionObj->DESTROY();
- return (1);
- };
- if ($@) {
- $RT::Logger->error( "Scrip " . $self->Id . " died. - " . $@ );
+ $RT::Logger->debug("Now commiting scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
+ unless ( $self->Commit( TicketObj => $args{'TicketObj'},
+ TransactionObj => $ApplicableTransactionObj)
+ ) {
+ return undef;
}
+ $RT::Logger->debug("We actually finished scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
+ return (1);
+
}
+
# }}}
# {{{ sub IsApplicable
@@ -380,16 +382,69 @@ sub Apply {
Calls the Condition object\'s IsApplicable method
+Upon success, returns the applicable Transaction object.
+Otherwise, undef is returned.
+
+If the Scrip is in the TransactionCreate Stage (the usual case), only test
+the associated Transaction object to see if it is applicable.
+
+For Scrips in the TransactionBatch Stage, test all Transaction objects
+created during the Ticket object's lifetime, and returns the first one
+that is applicable.
+
=cut
sub IsApplicable {
my $self = shift;
- return ($self->ConditionObj->IsApplicable(@_));
+ my %args = ( TicketObj => undef,
+ TransactionObj => undef,
+ @_ );
+
+ my $return;
+ eval {
+
+ my @Transactions;
+
+ if ( $self->Stage eq 'TransactionCreate') {
+ # Only look at our current Transaction
+ @Transactions = ( $args{'TransactionObj'} );
+ }
+ elsif ( $self->Stage eq 'TransactionBatch') {
+ # Look at all Transactions in this Batch
+ @Transactions = @{ $args{'TicketObj'}->TransactionBatch || [] };
+ }
+ else {
+ $RT::Logger->error( "Unknown Scrip stage:" . $self->Stage );
+ return (undef);
+ }
+
+ foreach my $TransactionObj ( @Transactions ) {
+ # Load the scrip's Condition object
+ $self->ConditionObj->LoadCondition(
+ ScripObj => $self,
+ TicketObj => $args{'TicketObj'},
+ TransactionObj => $TransactionObj,
+ );
+
+ if ( $self->ConditionObj->IsApplicable() ) {
+ # We found an application Transaction -- return it
+ $return = $TransactionObj;
+ last;
+ }
+ }
+ };
+ if ($@) {
+ $RT::Logger->error( "Scrip IsApplicable " . $self->Id . " died. - " . $@ );
+ return (undef);
+ }
+
+ return ($return);
+
}
# }}}
-# {{{ sub Prepare
+# {{{ SUb Prepare
=head2 Prepare
@@ -399,7 +454,26 @@ Calls the action object's prepare method
sub Prepare {
my $self = shift;
- $self->ActionObj->Prepare(@_);
+ my %args = ( TicketObj => undef,
+ TransactionObj => undef,
+ @_ );
+
+ my $return;
+ eval {
+ $self->ActionObj->LoadAction( ScripObj => $self,
+ TicketObj => $args{'TicketObj'},
+ TransactionObj => $args{'TransactionObj'},
+ );
+
+ $return = $self->ActionObj->Prepare();
+ };
+ if ($@) {
+ $RT::Logger->error( "Scrip Prepare " . $self->Id . " died. - " . $@ );
+ return (undef);
+ }
+ unless ($return) {
+ }
+ return ($return);
}
# }}}
@@ -414,18 +488,32 @@ Calls the action object's commit method
sub Commit {
my $self = shift;
- $self->ActionObj->Commit(@_);
-}
+ my %args = ( TicketObj => undef,
+ TransactionObj => undef,
+ @_ );
-# }}}
+ my $return;
+ eval {
+ $return = $self->ActionObj->Commit();
+ };
-# }}}
+#Searchbuilder caching isn't perfectly coherent. got to reload the ticket object, since it
+# may have changed
+ $args{'TicketObj'}->Load( $args{'TicketObj'}->Id );
-# {{{ sub DESTROY
-sub DESTROY {
- my $self = shift;
- $self->{'ActionObj'} = undef;
+ if ($@) {
+ $RT::Logger->error( "Scrip IsApplicable " . $self->Id . " died. - " . $@ );
+ return (undef);
+ }
+
+ # Not destroying or weakening hte Action and Condition here could cause a
+ # leak
+
+ return ($return);
}
+
+# }}}
+
# }}}
# {{{ ACL related methods
@@ -435,10 +523,11 @@ sub DESTROY {
# does an acl check and then passes off the call
sub _Set {
my $self = shift;
-
- unless ($self->CurrentUserHasRight('ModifyScrips')) {
- $RT::Logger->debug("CurrentUser can't modify Scrips for ".$self->Queue."\n");
- return (0, $self->loc('Permission Denied'));
+
+ unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
+ $RT::Logger->debug(
+ "CurrentUser can't modify Scrips for " . $self->Queue . "\n" );
+ return ( 0, $self->loc('Permission Denied') );
}
return $self->__Set(@_);
}
@@ -449,14 +538,17 @@ sub _Set {
# does an acl check and then passes off the call
sub _Value {
my $self = shift;
-
- unless ($self->CurrentUserHasRight('ShowScrips')) {
- $RT::Logger->debug("CurrentUser can't modify Scrips for ".$self->__Value('Queue')."\n");
- return (undef);
+
+ unless ( $self->CurrentUserHasRight('ShowScrips') ) {
+ $RT::Logger->debug( "CurrentUser can't modify Scrips for "
+ . $self->__Value('Queue')
+ . "\n" );
+ return (undef);
}
-
+
return $self->__Value(@_);
}
+
# }}}
# {{{ sub CurrentUserHasRight
@@ -469,11 +561,11 @@ calls HasRight.
=cut
sub CurrentUserHasRight {
- my $self = shift;
+ my $self = shift;
my $right = shift;
- return ($self->HasRight( Principal => $self->CurrentUser->UserObj,
- Right => $right ));
-
+ return ( $self->HasRight( Principal => $self->CurrentUser->UserObj,
+ Right => $right ) );
+
}
# }}}
@@ -490,26 +582,25 @@ Right string that applies to Scrips.
sub HasRight {
my $self = shift;
- my %args = ( Right => undef,
+ my %args = ( Right => undef,
Principal => undef,
@_ );
-
- if ((defined $self->SUPER::_Value('Queue')) and ($self->SUPER::_Value('Queue') != 0)) {
- return ( $args{'Principal'}->HasRight(
- Right => $args{'Right'},
- Object => $self->QueueObj
- )
- );
-
+
+ if ( ( defined $self->SUPER::_Value('Queue') )
+ and ( $self->SUPER::_Value('Queue') != 0 ) ) {
+ return ( $args{'Principal'}->HasRight( Right => $args{'Right'},
+ Object => $self->QueueObj ) );
+
}
else {
- return( $args{'Principal'}->HasRight( Object => $RT::System, Right => $args{'Right'}) );
+ return ( $args{'Principal'}
+ ->HasRight( Object => $RT::System, Right => $args{'Right'} ) );
}
}
+
# }}}
# }}}
1;
-