3 # Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
5 # (Except where explictly superceded by other copyright notices)
7 # This work is made available to you under the terms of Version 2 of
8 # the GNU General Public License. A copy of that license should have
9 # been provided with this software, but in any event can be snarfed
12 # This work is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # General Public License for more details.
17 # Unless otherwise specified, all modifications, corrections or
18 # extensions to this work which alter its source code become the
19 # property of Best Practical Solutions, LLC when submitted for
20 # inclusion in the work.
26 RT::Scrip - an RT Scrip object
39 ok (require RT::Scrip);
42 my $q = RT::Queue->new($RT::SystemUser);
43 $q->Create(Name => 'ScripTest');
44 ok($q->Id, "Created a scriptest queue");
46 my $s1 = RT::Scrip->new($RT::SystemUser);
47 my ($val, $msg) =$s1->Create( Queue => $q->Id,
48 ScripAction => 'User Defined',
49 ScripCondition => 'User Defined',
50 CustomIsApplicableCode => 'if ($self->TicketObj->Subject =~ /fire/) { return (1);} else { return(0)}',
51 CustomPrepareCode => 'return 1',
52 CustomCommitCode => '$self->TicketObj->SetPriority("87");',
57 my $ticket = RT::Ticket->new($RT::SystemUser);
58 my ($tv,$ttv,$tm) = $ticket->Create(Queue => $q->Id,
59 Subject => "hair on fire",
63 ok ($ticket->Priority == '87', "Ticket priority is set right");
66 my $ticket2 = RT::Ticket->new($RT::SystemUser);
67 my ($t2v,$t2tv,$t2m) = $ticket2->Create(Queue => $q->Id,
68 Subject => "hair in water",
72 ok ($ticket2->Priority != '87', "Ticket priority is set right");
80 no warnings qw(redefine);
87 Creates a new entry in the Scrips table. Takes a paramhash with:
93 ScripCondition => undef,
94 CustomPrepareCode => undef,
95 CustomCommitCode => undef,
96 CustomIsApplicableCode => undef,
101 Returns (retval, msg);
102 retval is 0 for failure or scrip id. msg is a textual description of what happened.
110 Template => 0, # name or id
111 ScripAction => 0, # name or id
112 ScripCondition => 0, # name or id
113 Stage => 'TransactionCreate',
114 Description => undef,
115 CustomPrepareCode => undef,
116 CustomCommitCode => undef,
117 CustomIsApplicableCode => undef,
123 if (! $args{'Queue'} ) {
124 unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'ModifyScrips') ) {
125 return ( 0, $self->loc('Permission Denied') );
127 $args{'Queue'} = 0; # avoid undef sneaking in
130 my $QueueObj = new RT::Queue( $self->CurrentUser );
131 $QueueObj->Load( $args{'Queue'} );
132 unless ( $QueueObj->id() ) {
133 return ( 0, $self->loc('Invalid queue') );
135 unless ( $QueueObj->CurrentUserHasRight('ModifyScrips') ) {
136 return ( 0, $self->loc('Permission Denied') );
138 $args{'Queue'} = $QueueObj->id();
141 #TODO +++ validate input
143 require RT::ScripAction;
144 my $action = new RT::ScripAction( $self->CurrentUser );
145 $action->Load( $args{'ScripAction'} || '0' );
146 return ( 0, $self->loc( "Action [_1] not found", $args{'ScripAction'} ) )
149 require RT::Template;
150 my $template = new RT::Template( $self->CurrentUser );
151 $template->Load( $args{'Template'}||'0' );
152 return ( 0, $self->loc('Template not found') ) unless $template->Id;
154 require RT::ScripCondition;
155 my $condition = new RT::ScripCondition( $self->CurrentUser );
156 $condition->Load( $args{'ScripCondition'}||'0' );
158 unless ( $condition->Id ) {
159 return ( 0, $self->loc('Condition not found') );
162 my ($id,$msg) = $self->SUPER::Create(
163 Queue => $args{'Queue'},
164 Template => $template->Id,
165 ScripCondition => $condition->id,
166 Stage => $args{'Stage'},
167 ScripAction => $action->Id,
168 Description => $args{'Description'},
169 CustomPrepareCode => $args{'CustomPrepareCode'},
170 CustomCommitCode => $args{'CustomCommitCode'},
171 CustomIsApplicableCode => $args{'CustomIsApplicableCode'},
175 return ( $id, $self->loc('Scrip Created') );
195 unless ($self->CurrentUserHasRight('ModifyScrips')) {
196 return (0, $self->loc('Permission Denied'));
199 return ($self->SUPER::Delete(@_));
207 Retuns an RT::Queue object with this Scrip\'s queue
214 if (!$self->{'QueueObj'}) {
216 $self->{'QueueObj'} = RT::Queue->new($self->CurrentUser);
217 $self->{'QueueObj'}->Load($self->__Value('Queue'));
219 return ($self->{'QueueObj'});
229 Retuns an RT::Action object with this Scrip\'s Action
236 unless (defined $self->{'ScripActionObj'}) {
237 require RT::ScripAction;
239 $self->{'ScripActionObj'} = RT::ScripAction->new($self->CurrentUser);
240 #TODO: why are we loading Actions with templates like this.
241 # two seperate methods might make more sense
242 $self->{'ScripActionObj'}->Load($self->ScripAction, $self->Template);
244 return ($self->{'ScripActionObj'});
249 # {{{ sub ConditionObj
253 Retuns an RT::ScripCondition object with this Scrip's IsApplicable
260 unless (defined $self->{'ScripConditionObj'}) {
261 require RT::ScripCondition;
262 $self->{'ScripConditionObj'} = RT::ScripCondition->new($self->CurrentUser);
263 $self->{'ScripConditionObj'}->Load($self->ScripCondition);
265 return ($self->{'ScripConditionObj'});
270 # {{{ sub TemplateObj
273 Retuns an RT::Template object with this Scrip\'s Template
280 unless (defined $self->{'TemplateObj'}) {
281 require RT::Template;
282 $self->{'TemplateObj'} = RT::Template->new($self->CurrentUser);
283 $self->{'TemplateObj'}->Load($self->Template);
285 return ($self->{'TemplateObj'});
291 # {{{ Dealing with this instance of a scrip
293 =head2 Apply { TicketObj => undef, TransactionObj => undef}
295 This method instantiates the ScripCondition and ScripAction objects for a
296 single execution of this scrip. it then calls the IsApplicable method of the
298 If that succeeds, it calls the Prepare method of the
299 ScripAction. If that succeeds, it calls the Commit method of the ScripAction.
301 Usually, the ticket and transaction objects passed to this method
302 should be loaded by the SuperUser role
311 my %args = ( TicketObj => undef,
312 TransactionObj => undef,
315 # We want to make sure that if a scrip dies, we don't get
319 #Load the scrip's Condition object
320 $self->ConditionObj->LoadCondition(
322 TicketObj => $args{'TicketObj'},
323 TransactionObj => $args{'TransactionObj'},
326 unless ( $self->IsApplicable() ) {
327 $self->ConditionObj->DESTROY;
331 #If it's applicable, prepare and commit it
332 $self->ActionObj->LoadAction( ScripObj => $self,
333 TicketObj => $args{'TicketObj'},
334 TransactionObj => $args{'TransactionObj'},
337 unless ( $self->Prepare() ) {
339 "$self: Couldn't prepare " . $self->ActionObj->Name );
340 $self->ActionObj->DESTROY();
341 $self->ConditionObj->DESTROY();
344 unless ( $self->Commit() ) {
346 "$self: Couldn't commit " . $self->ActionObj->Name );
347 $self->ActionObj->DESTROY();
348 $self->ConditionObj->DESTROY();
352 #Searchbuilder caching isn't perfectly coherent. got to reload the ticket object, since it
354 $args{'TicketObj'}->Load($args{'TicketObj'}->Id);
356 #We're done with it. lets clean up.
357 #TODO: something else isn't letting these get garbage collected. check em out.
358 $self->ActionObj->DESTROY();
359 $self->ConditionObj->DESTROY();
363 $RT::Logger->error( "Scrip " . $self->Id . " died. - " . $@ );
369 # {{{ sub IsApplicable
373 Calls the Condition object\'s IsApplicable method
379 return ($self->ConditionObj->IsApplicable(@_));
388 Calls the action object's prepare method
394 $self->ActionObj->Prepare(@_);
403 Calls the action object's commit method
409 $self->ActionObj->Commit(@_);
419 $self->{'ActionObj'} = undef;
423 # {{{ ACL related methods
427 # does an acl check and then passes off the call
431 unless ($self->CurrentUserHasRight('ModifyScrips')) {
432 $RT::Logger->debug("CurrentUser can't modify Scrips for ".$self->Queue."\n");
433 return (0, $self->loc('Permission Denied'));
435 return $self->__Set(@_);
441 # does an acl check and then passes off the call
445 unless ($self->CurrentUserHasRight('ShowScrips')) {
446 $RT::Logger->debug("CurrentUser can't modify Scrips for ".$self->__Value('Queue')."\n");
450 return $self->__Value(@_);
454 # {{{ sub CurrentUserHasRight
456 =head2 CurrentUserHasRight
458 Helper menthod for HasRight. Presets Principal to CurrentUser then
463 sub CurrentUserHasRight {
466 return ($self->HasRight( Principal => $self->CurrentUser->UserObj,
477 Takes a param-hash consisting of "Right" and "Principal" Principal is
478 an RT::User object or an RT::CurrentUser object. "Right" is a textual
479 Right string that applies to Scrips.
485 my %args = ( Right => undef,
489 if ((defined $self->SUPER::_Value('Queue')) and ($self->SUPER::_Value('Queue') != 0)) {
490 return ( $args{'Principal'}->HasRight(
491 Right => $args{'Right'},
492 Object => $self->QueueObj
498 return( $args{'Principal'}->HasRight( Object => $RT::System, Right => $args{'Right'}) );