Upgrade to 4.2.8
[usit-rt.git] / lib / RT / Scrip.pm
CommitLineData
84fb5b46
MKG
1# BEGIN BPS TAGGED BLOCK {{{
2#
3# COPYRIGHT:
4#
3ffc5f4f 5# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
84fb5b46
MKG
6# <sales@bestpractical.com>
7#
8# (Except where explicitly superseded by other copyright notices)
9#
10#
11# LICENSE:
12#
13# This work is made available to you under the terms of Version 2 of
14# the GNU General Public License. A copy of that license should have
15# been provided with this software, but in any event can be snarfed
16# from www.gnu.org.
17#
18# This work is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26# 02110-1301 or visit their web page on the internet at
27# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28#
29#
30# CONTRIBUTION SUBMISSION POLICY:
31#
32# (The following paragraph is not intended to limit the rights granted
33# to you to modify and distribute this software under the terms of
34# the GNU General Public License and is only of importance to you if
35# you choose to contribute your changes and enhancements to the
36# community by submitting them to Best Practical Solutions, LLC.)
37#
38# By intentionally submitting any modifications, corrections or
39# derivatives to this work, or any other work intended for use with
40# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41# you are the copyright holder for those contributions and you grant
42# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43# royalty-free, perpetual, license to use, copy, create derivative
44# works based on those contributions, and sublicense and distribute
45# those contributions and any derivatives thereof.
46#
47# END BPS TAGGED BLOCK }}}
48
49=head1 NAME
50
51 RT::Scrip - an RT Scrip object
52
53=head1 SYNOPSIS
54
55 use RT::Scrip;
56
57=head1 DESCRIPTION
58
59
60=head1 METHODS
61
62
63=cut
64
65
66package RT::Scrip;
67
68use strict;
69use warnings;
3ffc5f4f 70use base 'RT::Record';
84fb5b46
MKG
71
72use RT::Queue;
73use RT::Template;
74use RT::ScripCondition;
75use RT::ScripAction;
3ffc5f4f
MKG
76use RT::Scrips;
77use RT::ObjectScrip;
84fb5b46
MKG
78
79sub Table {'Scrips'}
80
81# {{{ sub Create
82
83=head2 Create
84
85Creates a new entry in the Scrips table. Takes a paramhash with:
86
87 Queue => 0,
88 Description => undef,
89 Template => undef,
90 ScripAction => undef,
91 ScripCondition => undef,
92 CustomPrepareCode => undef,
93 CustomCommitCode => undef,
94 CustomIsApplicableCode => undef,
95
96
97
98
99Returns (retval, msg);
100retval is 0 for failure or scrip id. msg is a textual description of what happened.
101
102=cut
103
104sub Create {
105 my $self = shift;
106 my %args = (
107 Queue => 0,
3ffc5f4f 108 Template => undef, # name or id
84fb5b46
MKG
109 ScripAction => 0, # name or id
110 ScripCondition => 0, # name or id
111 Stage => 'TransactionCreate',
112 Description => undef,
113 CustomPrepareCode => undef,
114 CustomCommitCode => undef,
115 CustomIsApplicableCode => undef,
116 @_
117 );
118
119 if ($args{CustomPrepareCode} || $args{CustomCommitCode} || $args{CustomIsApplicableCode}) {
120 unless ( $self->CurrentUser->HasRight( Object => $RT::System,
121 Right => 'ExecuteCode' ) )
122 {
123 return ( 0, $self->loc('Permission Denied') );
124 }
125 }
126
127 unless ( $args{'Queue'} ) {
128 unless ( $self->CurrentUser->HasRight( Object => $RT::System,
129 Right => 'ModifyScrips' ) )
130 {
131 return ( 0, $self->loc('Permission Denied') );
132 }
133 $args{'Queue'} = 0; # avoid undef sneaking in
134 }
135 else {
136 my $QueueObj = RT::Queue->new( $self->CurrentUser );
137 $QueueObj->Load( $args{'Queue'} );
138 unless ( $QueueObj->id ) {
139 return ( 0, $self->loc('Invalid queue') );
140 }
141 unless ( $QueueObj->CurrentUserHasRight('ModifyScrips') ) {
142 return ( 0, $self->loc('Permission Denied') );
143 }
144 $args{'Queue'} = $QueueObj->id;
145 }
146
147 #TODO +++ validate input
148
84fb5b46
MKG
149 return ( 0, $self->loc("Action is mandatory argument") )
150 unless $args{'ScripAction'};
151 my $action = RT::ScripAction->new( $self->CurrentUser );
152 $action->Load( $args{'ScripAction'} );
153 return ( 0, $self->loc( "Action '[_1]' not found", $args{'ScripAction'} ) )
154 unless $action->Id;
155
84fb5b46
MKG
156 return ( 0, $self->loc("Template is mandatory argument") )
157 unless $args{'Template'};
158 my $template = RT::Template->new( $self->CurrentUser );
3ffc5f4f
MKG
159 if ( $args{'Template'} =~ /\D/ ) {
160 $template->LoadByName( Name => $args{'Template'}, Queue => $args{'Queue'} );
161 return ( 0, $self->loc( "Global template '[_1]' not found", $args{'Template'} ) )
162 if !$template->Id && !$args{'Queue'};
163 return ( 0, $self->loc( "Global or queue specific template '[_1]' not found", $args{'Template'} ) )
164 if !$template->Id;
165 } else {
166 $template->Load( $args{'Template'} );
167 return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) )
168 unless $template->Id;
169
170 return (0, $self->loc( "Template '[_1]' is not global" ))
171 if !$args{'Queue'} && $template->Queue;
172 return (0, $self->loc( "Template '[_1]' is not global nor queue specific" ))
173 if $args{'Queue'} && $template->Queue && $template->Queue != $args{'Queue'};
174 }
84fb5b46 175
84fb5b46
MKG
176 return ( 0, $self->loc("Condition is mandatory argument") )
177 unless $args{'ScripCondition'};
178 my $condition = RT::ScripCondition->new( $self->CurrentUser );
179 $condition->Load( $args{'ScripCondition'} );
180 return ( 0, $self->loc( "Condition '[_1]' not found", $args{'ScripCondition'} ) )
181 unless $condition->Id;
182
3ffc5f4f
MKG
183 if ( $args{'Stage'} eq 'Disabled' ) {
184 $RT::Logger->warning("Disabled Stage is deprecated");
185 $args{'Stage'} = 'TransactionCreate';
186 $args{'Disabled'} = 1;
187 }
188 $args{'Disabled'} ||= 0;
189
84fb5b46 190 my ( $id, $msg ) = $self->SUPER::Create(
3ffc5f4f 191 Template => $template->Name,
84fb5b46 192 ScripCondition => $condition->id,
84fb5b46 193 ScripAction => $action->Id,
3ffc5f4f 194 Disabled => $args{'Disabled'},
84fb5b46
MKG
195 Description => $args{'Description'},
196 CustomPrepareCode => $args{'CustomPrepareCode'},
197 CustomCommitCode => $args{'CustomCommitCode'},
198 CustomIsApplicableCode => $args{'CustomIsApplicableCode'},
199 );
3ffc5f4f
MKG
200 return ( $id, $msg ) unless $id;
201
202 (my $status, $msg) = RT::ObjectScrip->new( $self->CurrentUser )->Add(
203 Scrip => $self,
204 Stage => $args{'Stage'},
205 ObjectId => $args{'Queue'},
206 );
207 $RT::Logger->error( "Couldn't add scrip: $msg" ) unless $status;
208
209 return ( $id, $self->loc('Scrip Created') );
84fb5b46
MKG
210}
211
212
213
214=head2 Delete
215
216Delete this object
217
218=cut
219
220sub Delete {
221 my $self = shift;
222
223 unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
224 return ( 0, $self->loc('Permission Denied') );
225 }
226
3ffc5f4f
MKG
227 RT::ObjectScrip->new( $self->CurrentUser )->DeleteAll( Scrip => $self );
228
84fb5b46
MKG
229 return ( $self->SUPER::Delete(@_) );
230}
231
3ffc5f4f
MKG
232sub IsGlobal { return shift->IsAdded(0) }
233
234sub IsAdded {
235 my $self = shift;
236 my $record = RT::ObjectScrip->new( $self->CurrentUser );
237 $record->LoadByCols( Scrip => $self->id, ObjectId => shift || 0 );
238 return undef unless $record->id;
239 return $record;
240}
241
242sub IsAddedToAny {
243 my $self = shift;
244 my $record = RT::ObjectScrip->new( $self->CurrentUser );
245 $record->LoadByCols( Scrip => $self->id );
246 return $record->id ? 1 : 0;
247}
248
249sub AddedTo {
250 my $self = shift;
251 return RT::ObjectScrip->new( $self->CurrentUser )
252 ->AddedTo( Scrip => $self );
253}
254
255sub NotAddedTo {
256 my $self = shift;
257 return RT::ObjectScrip->new( $self->CurrentUser )
258 ->NotAddedTo( Scrip => $self );
259}
260
261=head2 AddToObject
262
263Adds (applies) the current scrip to the provided queue (ObjectId).
264
265Accepts a param hash of:
266
267=over
268
269=item C<ObjectId>
270
271Queue name or id. 0 makes the scrip global.
272
273=item C<Stage>
274
275Stage to run in. Valid stages are TransactionCreate or
276TransactionBatch. Defaults to TransactionCreate. As of RT 4.2, Disabled
277is no longer a stage.
278
279=item C<Template>
280
281Name of global or queue-specific template for the scrip. Use 'Blank' for
282non-notification scrips.
84fb5b46 283
3ffc5f4f 284=item C<SortOrder>
84fb5b46 285
3ffc5f4f 286Number indicating the relative order the scrip should run in.
84fb5b46 287
3ffc5f4f
MKG
288=back
289
290Returns (val, message). If val is false, the message contains an error
291message.
84fb5b46
MKG
292
293=cut
294
3ffc5f4f 295sub AddToObject {
84fb5b46 296 my $self = shift;
3ffc5f4f
MKG
297 my %args = @_%2? (ObjectId => @_) : (@_);
298
299 # Default Stage explicitly rather than in %args assignment to handle
300 # Stage coming in set to undef.
301 $args{'Stage'} //= 'TransactionCreate';
302
303 my $queue;
304 if ( $args{'ObjectId'} ) {
305 $queue = RT::Queue->new( $self->CurrentUser );
306 $queue->Load( $args{'ObjectId'} );
307 return (0, $self->loc('Invalid queue'))
308 unless $queue->id;
309
310 $args{'ObjectId'} = $queue->id;
311 }
312 return ( 0, $self->loc('Permission Denied') )
313 unless $self->CurrentUser->PrincipalObj->HasRight(
314 Object => $queue || $RT::System, Right => 'ModifyScrips',
315 )
316 ;
84fb5b46 317
3ffc5f4f
MKG
318 my $tname = $self->Template;
319 my $template = RT::Template->new( $self->CurrentUser );
320 $template->LoadByName( Queue => $queue? $queue->id : 0, Name => $tname );
321 unless ( $template->id ) {
322 if ( $queue ) {
323 return (0, $self->loc('No template [_1] in queue [_2] or global',
324 $tname, $queue->Name||$queue->id));
325 } else {
326 return (0, $self->loc('No global template [_1]', $tname));
327 }
84fb5b46 328 }
3ffc5f4f
MKG
329
330 my $rec = RT::ObjectScrip->new( $self->CurrentUser );
331 return $rec->Add( %args, Scrip => $self );
84fb5b46
MKG
332}
333
3ffc5f4f
MKG
334=head2 RemoveFromObject
335
336Removes the current scrip to the provided queue (ObjectId).
337
338Accepts a param hash of:
84fb5b46 339
3ffc5f4f
MKG
340=over
341
342=item C<ObjectId>
343
344Queue name or id. 0 makes the scrip global.
345
346=back
347
348Returns (val, message). If val is false, the message contains an error
349message.
350
351=cut
352
353sub RemoveFromObject {
354 my $self = shift;
355 my %args = @_%2? (ObjectId => @_) : (@_);
356
357 my $queue;
358 if ( $args{'ObjectId'} ) {
359 $queue = RT::Queue->new( $self->CurrentUser );
360 $queue->Load( $args{'ObjectId'} );
361 return (0, $self->loc('Invalid queue id'))
362 unless $queue->id;
363 }
364 return ( 0, $self->loc('Permission Denied') )
365 unless $self->CurrentUser->PrincipalObj->HasRight(
366 Object => $queue || $RT::System, Right => 'ModifyScrips',
367 )
368 ;
369
370 my $rec = RT::ObjectScrip->new( $self->CurrentUser );
371 $rec->LoadByCols( Scrip => $self->id, ObjectId => $args{'ObjectId'} );
372 return (0, $self->loc('Scrip is not added') ) unless $rec->id;
373 return $rec->Delete;
374}
84fb5b46
MKG
375
376=head2 ActionObj
377
403d7b0b 378Retuns an RT::Action object with this Scrip's Action
84fb5b46
MKG
379
380=cut
381
382sub ActionObj {
383 my $self = shift;
384
385 unless ( defined $self->{'ScripActionObj'} ) {
386 require RT::ScripAction;
84fb5b46 387 $self->{'ScripActionObj'} = RT::ScripAction->new( $self->CurrentUser );
3ffc5f4f 388 $self->{'ScripActionObj'}->Load( $self->ScripAction );
84fb5b46
MKG
389 }
390 return ( $self->{'ScripActionObj'} );
391}
392
393
394
395=head2 ConditionObj
396
397Retuns an L<RT::ScripCondition> object with this Scrip's IsApplicable
398
399=cut
400
401sub ConditionObj {
402 my $self = shift;
403
404 my $res = RT::ScripCondition->new( $self->CurrentUser );
405 $res->Load( $self->ScripCondition );
406 return $res;
407}
408
409
410=head2 LoadModules
411
412Loads scrip's condition and action modules.
413
414=cut
415
416sub LoadModules {
417 my $self = shift;
418
419 $self->ConditionObj->LoadCondition;
420 $self->ActionObj->LoadAction;
421}
422
423
424=head2 TemplateObj
425
403d7b0b 426Retuns an RT::Template object with this Scrip's Template
84fb5b46
MKG
427
428=cut
429
430sub TemplateObj {
431 my $self = shift;
3ffc5f4f 432 my $queue = shift;
84fb5b46 433
3ffc5f4f
MKG
434 my $res = RT::Template->new( $self->CurrentUser );
435 $res->LoadByName( Queue => $queue, Name => $self->Template );
436 return $res;
437}
438
439=head2 Stage
440
441Takes TicketObj named argument and returns scrip's stage when
442added to ticket's queue.
443
444=cut
445
446sub Stage {
447 my $self = shift;
448 my %args = ( TicketObj => undef, @_ );
449
450 my $queue = $args{'TicketObj'}->Queue;
451 my $rec = RT::ObjectScrip->new( $self->CurrentUser );
452 $rec->LoadByCols( Scrip => $self->id, ObjectId => $queue );
453 return $rec->Stage if $rec->id;
454
455 $rec->LoadByCols( Scrip => $self->id, ObjectId => 0 );
456 return $rec->Stage if $rec->id;
457
458 return undef;
84fb5b46
MKG
459}
460
3ffc5f4f 461=head2 FriendlyStage($Stage)
84fb5b46 462
3ffc5f4f
MKG
463Helper function that returns a localized human-readable version of the
464C<$Stage> argument.
465
466=cut
84fb5b46 467
3ffc5f4f
MKG
468sub FriendlyStage {
469 my ( $class, $stage ) = @_;
470 my $stage_i18n_lookup = {
471 TransactionCreate => 'Normal', # loc
472 TransactionBatch => 'Batch', # loc
473 TransactionBatchDisabled => 'Batch (disabled by config)', # loc
474 };
475 $stage = 'TransactionBatchDisabled'
476 if $stage eq 'TransactionBatch'
477 and not RT->Config->Get('UseTransactionBatch');
478 return $stage_i18n_lookup->{$stage};
479}
84fb5b46
MKG
480
481=head2 Apply { TicketObj => undef, TransactionObj => undef}
482
483This method instantiates the ScripCondition and ScripAction objects for a
484single execution of this scrip. it then calls the IsApplicable method of the
485ScripCondition.
486If that succeeds, it calls the Prepare method of the
487ScripAction. If that succeeds, it calls the Commit method of the ScripAction.
488
489Usually, the ticket and transaction objects passed to this method
490should be loaded by the SuperUser role
491
492=cut
493
494
495# XXX TODO : This code appears to be obsoleted in favor of similar code in Scrips->Apply.
496# Why is this here? Is it still called?
497
498sub Apply {
499 my $self = shift;
500 my %args = ( TicketObj => undef,
501 TransactionObj => undef,
502 @_ );
503
504 $RT::Logger->debug("Now applying scrip ".$self->Id . " for transaction ".$args{'TransactionObj'}->id);
505
506 my $ApplicableTransactionObj = $self->IsApplicable( TicketObj => $args{'TicketObj'},
507 TransactionObj => $args{'TransactionObj'} );
508 unless ( $ApplicableTransactionObj ) {
509 return undef;
510 }
511
512 if ( $ApplicableTransactionObj->id != $args{'TransactionObj'}->id ) {
513 $RT::Logger->debug("Found an applicable transaction ".$ApplicableTransactionObj->Id . " in the same batch with transaction ".$args{'TransactionObj'}->id);
514 }
515
516 #If it's applicable, prepare and commit it
517 $RT::Logger->debug("Now preparing scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
518 unless ( $self->Prepare( TicketObj => $args{'TicketObj'},
519 TransactionObj => $ApplicableTransactionObj )
520 ) {
521 return undef;
522 }
523
524 $RT::Logger->debug("Now commiting scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
525 unless ( $self->Commit( TicketObj => $args{'TicketObj'},
526 TransactionObj => $ApplicableTransactionObj)
527 ) {
528 return undef;
529 }
530
531 $RT::Logger->debug("We actually finished scrip ".$self->Id . " for transaction ".$ApplicableTransactionObj->id);
532 return (1);
533
534}
535
536
537
538=head2 IsApplicable
539
403d7b0b 540Calls the Condition object's IsApplicable method
84fb5b46
MKG
541
542Upon success, returns the applicable Transaction object.
543Otherwise, undef is returned.
544
545If the Scrip is in the TransactionCreate Stage (the usual case), only test
546the associated Transaction object to see if it is applicable.
547
548For Scrips in the TransactionBatch Stage, test all Transaction objects
549created during the Ticket object's lifetime, and returns the first one
550that is applicable.
551
552=cut
553
554sub IsApplicable {
555 my $self = shift;
556 my %args = ( TicketObj => undef,
557 TransactionObj => undef,
558 @_ );
559
560 my $return;
561 eval {
562
3ffc5f4f 563 my @Transactions;
84fb5b46 564
3ffc5f4f
MKG
565 my $stage = $self->Stage( TicketObj => $args{'TicketObj'} );
566 unless ( $stage ) {
567 $RT::Logger->error(
568 "Scrip #". $self->id ." is not applied to"
569 ." queue #". $args{'TicketObj'}->Queue
570 );
571 return (undef);
572 }
573 elsif ( $stage eq 'TransactionCreate') {
574 # Only look at our current Transaction
575 @Transactions = ( $args{'TransactionObj'} );
84fb5b46 576 }
3ffc5f4f
MKG
577 elsif ( $stage eq 'TransactionBatch') {
578 # Look at all Transactions in this Batch
84fb5b46
MKG
579 @Transactions = @{ $args{'TicketObj'}->TransactionBatch || [] };
580 }
3ffc5f4f
MKG
581 else {
582 $RT::Logger->error( "Unknown Scrip stage: '$stage'" );
583 return (undef);
584 }
585 my $ConditionObj = $self->ConditionObj;
586 foreach my $TransactionObj ( @Transactions ) {
587 # in TxnBatch stage we can select scrips that are not applicable to all txns
588 my $txn_type = $TransactionObj->Type;
589 next unless( $ConditionObj->ApplicableTransTypes =~ /(?:^|,)(?:Any|\Q$txn_type\E)(?:,|$)/i );
590 # Load the scrip's Condition object
591 $ConditionObj->LoadCondition(
592 ScripObj => $self,
593 TicketObj => $args{'TicketObj'},
594 TransactionObj => $TransactionObj,
595 );
84fb5b46
MKG
596
597 if ( $ConditionObj->IsApplicable() ) {
3ffc5f4f 598 # We found an application Transaction -- return it
84fb5b46
MKG
599 $return = $TransactionObj;
600 last;
601 }
3ffc5f4f 602 }
84fb5b46
MKG
603 };
604
605 if ($@) {
606 $RT::Logger->error( "Scrip IsApplicable " . $self->Id . " died. - " . $@ );
607 return (undef);
608 }
609
610 return ($return);
611
612}
613
614
615
616=head2 Prepare
617
618Calls the action object's prepare method
619
620=cut
621
622sub Prepare {
623 my $self = shift;
624 my %args = ( TicketObj => undef,
625 TransactionObj => undef,
626 @_ );
627
628 my $return;
629 eval {
3ffc5f4f
MKG
630 $self->ActionObj->LoadAction(
631 ScripObj => $self,
632 TicketObj => $args{'TicketObj'},
633 TransactionObj => $args{'TransactionObj'},
634 TemplateObj => $self->TemplateObj( $args{'TicketObj'}->Queue ),
84fb5b46
MKG
635 );
636
637 $return = $self->ActionObj->Prepare();
638 };
639 if ($@) {
640 $RT::Logger->error( "Scrip Prepare " . $self->Id . " died. - " . $@ );
641 return (undef);
642 }
643 unless ($return) {
644 }
645 return ($return);
646}
647
648
649
650=head2 Commit
651
652Calls the action object's commit method
653
654=cut
655
656sub Commit {
657 my $self = shift;
658 my %args = ( TicketObj => undef,
659 TransactionObj => undef,
660 @_ );
661
662 my $return;
663 eval {
664 $return = $self->ActionObj->Commit();
665 };
666
667#Searchbuilder caching isn't perfectly coherent. got to reload the ticket object, since it
668# may have changed
669 $args{'TicketObj'}->Load( $args{'TicketObj'}->Id );
670
671 if ($@) {
672 $RT::Logger->error( "Scrip Commit " . $self->Id . " died. - " . $@ );
673 return (undef);
674 }
675
676 # Not destroying or weakening hte Action and Condition here could cause a
677 # leak
678
679 return ($return);
680}
681
682
683
684
685
686# does an acl check and then passes off the call
687sub _Set {
688 my $self = shift;
689 my %args = (
690 Field => undef,
691 Value => undef,
692 @_,
693 );
694
695 unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
3ffc5f4f 696 $RT::Logger->debug( "CurrentUser can't modify Scrips" );
84fb5b46
MKG
697 return ( 0, $self->loc('Permission Denied') );
698 }
699
700
701 if (exists $args{Value}) {
702 if ($args{Field} eq 'CustomIsApplicableCode' || $args{Field} eq 'CustomPrepareCode' || $args{Field} eq 'CustomCommitCode') {
703 unless ( $self->CurrentUser->HasRight( Object => $RT::System,
704 Right => 'ExecuteCode' ) ) {
705 return ( 0, $self->loc('Permission Denied') );
706 }
707 }
708 elsif ($args{Field} eq 'Queue') {
709 if ($args{Value}) {
710 # moving to another queue
711 my $queue = RT::Queue->new( $self->CurrentUser );
712 $queue->Load($args{Value});
713 unless ($queue->Id and $queue->CurrentUserHasRight('ModifyScrips')) {
714 return ( 0, $self->loc('Permission Denied') );
715 }
716 } else {
717 # moving to global
718 unless ($self->CurrentUser->HasRight( Object => RT->System, Right => 'ModifyScrips' )) {
719 return ( 0, $self->loc('Permission Denied') );
720 }
721 }
722 }
723 elsif ($args{Field} eq 'Template') {
724 my $template = RT::Template->new( $self->CurrentUser );
725 $template->Load($args{Value});
726 unless ($template->Id and $template->CurrentUserCanRead) {
727 return ( 0, $self->loc('Permission Denied') );
728 }
729 }
730 }
731
dab09ea8 732 return $self->SUPER::_Set(@_);
84fb5b46
MKG
733}
734
735
736# does an acl check and then passes off the call
737sub _Value {
738 my $self = shift;
739
3ffc5f4f 740 return unless $self->CurrentUserHasRight('ShowScrips');
84fb5b46
MKG
741
742 return $self->__Value(@_);
743}
744
3ffc5f4f 745=head2 ACLEquivalenceObjects
84fb5b46 746
3ffc5f4f
MKG
747Having rights on any of the queues the scrip applies to is equivalent to
748having rights on the scrip.
84fb5b46
MKG
749
750=cut
751
3ffc5f4f 752sub ACLEquivalenceObjects {
84fb5b46 753 my $self = shift;
3ffc5f4f
MKG
754 return unless $self->id;
755 return @{ $self->AddedTo->ItemsArrayRef };
84fb5b46
MKG
756}
757
758
759
760=head2 CompileCheck
761
762This routine compile-checks the custom prepare, commit, and is-applicable code
763to see if they are syntactically valid Perl. We eval them in a codeblock to
764avoid actually executing the code.
765
766If one of the fields has a compile error, only the first is reported.
767
768Returns an (ok, message) pair.
769
770=cut
771
772sub CompileCheck {
773 my $self = shift;
774
775 for my $method (qw/CustomPrepareCode CustomCommitCode CustomIsApplicableCode/) {
776 my $code = $self->$method;
777 next if !defined($code);
778
779 do {
780 no strict 'vars';
403d7b0b 781 eval "sub { $code \n }";
84fb5b46
MKG
782 };
783 next if !$@;
784
785 my $error = $@;
786 return (0, $self->loc("Couldn't compile [_1] codeblock '[_2]': [_3]", $method, $code, $error));
787 }
788}
789
790
791=head2 SetScripAction
792
793=cut
794
795sub SetScripAction {
796 my $self = shift;
797 my $value = shift;
798
799 return ( 0, $self->loc("Action is mandatory argument") ) unless $value;
800
801 require RT::ScripAction;
802 my $action = RT::ScripAction->new( $self->CurrentUser );
803 $action->Load($value);
804 return ( 0, $self->loc( "Action '[_1]' not found", $value ) )
805 unless $action->Id;
806
807 return $self->_Set( Field => 'ScripAction', Value => $action->Id );
808}
809
810=head2 SetScripCondition
811
812=cut
813
814sub SetScripCondition {
815 my $self = shift;
816 my $value = shift;
817
818 return ( 0, $self->loc("Condition is mandatory argument") )
819 unless $value;
820
821 require RT::ScripCondition;
822 my $condition = RT::ScripCondition->new( $self->CurrentUser );
823 $condition->Load($value);
824
825 return ( 0, $self->loc( "Condition '[_1]' not found", $value ) )
826 unless $condition->Id;
827
828 return $self->_Set( Field => 'ScripCondition', Value => $condition->Id );
829}
830
831=head2 SetTemplate
832
833=cut
834
835sub SetTemplate {
836 my $self = shift;
837 my $value = shift;
838
839 return ( 0, $self->loc("Template is mandatory argument") ) unless $value;
840
841 require RT::Template;
842 my $template = RT::Template->new( $self->CurrentUser );
843 $template->Load($value);
844 return ( 0, $self->loc( "Template '[_1]' not found", $value ) )
845 unless $template->Id;
846
3ffc5f4f 847 return $self->_Set( Field => 'Template', Value => $template->Name );
84fb5b46
MKG
848}
849
8501;
851
852
853
854
855
856
857=head2 id
858
859Returns the current value of id.
860(In the database, id is stored as int(11).)
861
862
863=cut
864
865
866=head2 Description
867
868Returns the current value of Description.
869(In the database, Description is stored as varchar(255).)
870
871
872
873=head2 SetDescription VALUE
874
875
876Set Description to VALUE.
877Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
878(In the database, Description will be stored as a varchar(255).)
879
880
881=cut
882
883
884=head2 ScripCondition
885
886Returns the current value of ScripCondition.
887(In the database, ScripCondition is stored as int(11).)
888
889
890
891=head2 SetScripCondition VALUE
892
893
894Set ScripCondition to VALUE.
895Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
896(In the database, ScripCondition will be stored as a int(11).)
897
898
899=cut
900
901
902=head2 ScripConditionObj
903
904Returns the ScripCondition Object which has the id returned by ScripCondition
905
906
907=cut
908
909sub ScripConditionObj {
3ffc5f4f
MKG
910 my $self = shift;
911 my $ScripCondition = RT::ScripCondition->new($self->CurrentUser);
912 $ScripCondition->Load($self->__Value('ScripCondition'));
913 return($ScripCondition);
84fb5b46
MKG
914}
915
916=head2 ScripAction
917
918Returns the current value of ScripAction.
919(In the database, ScripAction is stored as int(11).)
920
921
922
923=head2 SetScripAction VALUE
924
925
926Set ScripAction to VALUE.
927Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
928(In the database, ScripAction will be stored as a int(11).)
929
930
931=cut
932
933
934=head2 ScripActionObj
935
936Returns the ScripAction Object which has the id returned by ScripAction
937
938
939=cut
940
941sub ScripActionObj {
3ffc5f4f
MKG
942 my $self = shift;
943 my $ScripAction = RT::ScripAction->new($self->CurrentUser);
944 $ScripAction->Load($self->__Value('ScripAction'));
945 return($ScripAction);
84fb5b46
MKG
946}
947
84fb5b46
MKG
948=head2 CustomIsApplicableCode
949
950Returns the current value of CustomIsApplicableCode.
951(In the database, CustomIsApplicableCode is stored as text.)
952
953
954
955=head2 SetCustomIsApplicableCode VALUE
956
957
958Set CustomIsApplicableCode to VALUE.
959Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
960(In the database, CustomIsApplicableCode will be stored as a text.)
961
962
963=cut
964
965
966=head2 CustomPrepareCode
967
968Returns the current value of CustomPrepareCode.
969(In the database, CustomPrepareCode is stored as text.)
970
971
972
973=head2 SetCustomPrepareCode VALUE
974
975
976Set CustomPrepareCode to VALUE.
977Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
978(In the database, CustomPrepareCode will be stored as a text.)
979
980
981=cut
982
983
984=head2 CustomCommitCode
985
986Returns the current value of CustomCommitCode.
987(In the database, CustomCommitCode is stored as text.)
988
989
990
991=head2 SetCustomCommitCode VALUE
992
993
994Set CustomCommitCode to VALUE.
995Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
996(In the database, CustomCommitCode will be stored as a text.)
997
998
999=cut
1000
1001
3ffc5f4f 1002=head2 Disabled
84fb5b46 1003
3ffc5f4f
MKG
1004Returns the current value of Disabled.
1005(In the database, Disabled is stored as smallint(6).)
84fb5b46
MKG
1006
1007
1008
3ffc5f4f 1009=head2 SetDisabled VALUE
84fb5b46
MKG
1010
1011
3ffc5f4f 1012Set Disabled to VALUE.
84fb5b46 1013Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
3ffc5f4f 1014(In the database, Disabled will be stored as a smallint(6).)
84fb5b46
MKG
1015
1016
1017=cut
1018
1019
1020=head2 Template
1021
1022Returns the current value of Template.
3ffc5f4f 1023(In the database, Template is stored as varchar(200).)
84fb5b46
MKG
1024
1025
1026
1027=head2 SetTemplate VALUE
1028
1029
1030Set Template to VALUE.
1031Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
3ffc5f4f 1032(In the database, Template will be stored as a varchar(200).)
84fb5b46
MKG
1033
1034
1035=cut
1036
1037
1038=head2 Creator
1039
1040Returns the current value of Creator.
1041(In the database, Creator is stored as int(11).)
1042
1043
1044=cut
1045
1046
1047=head2 Created
1048
1049Returns the current value of Created.
1050(In the database, Created is stored as datetime.)
1051
1052
1053=cut
1054
1055
1056=head2 LastUpdatedBy
1057
1058Returns the current value of LastUpdatedBy.
1059(In the database, LastUpdatedBy is stored as int(11).)
1060
1061
1062=cut
1063
1064
1065=head2 LastUpdated
1066
1067Returns the current value of LastUpdated.
1068(In the database, LastUpdated is stored as datetime.)
1069
1070
1071=cut
1072
1073
1074
1075sub _CoreAccessible {
1076 {
1077
1078 id =>
3ffc5f4f 1079 {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
84fb5b46 1080 Description =>
3ffc5f4f 1081 {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
84fb5b46 1082 ScripCondition =>
3ffc5f4f 1083 {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
84fb5b46 1084 ScripAction =>
3ffc5f4f 1085 {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
84fb5b46 1086 CustomIsApplicableCode =>
3ffc5f4f 1087 {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
84fb5b46 1088 CustomPrepareCode =>
3ffc5f4f 1089 {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
84fb5b46 1090 CustomCommitCode =>
3ffc5f4f
MKG
1091 {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
1092 Disabled =>
1093 {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'},
84fb5b46 1094 Template =>
3ffc5f4f 1095 {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => 'Blank'},
84fb5b46 1096 Creator =>
3ffc5f4f 1097 {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
84fb5b46 1098 Created =>
3ffc5f4f 1099 {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
84fb5b46 1100 LastUpdatedBy =>
3ffc5f4f 1101 {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
84fb5b46 1102 LastUpdated =>
3ffc5f4f 1103 {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
84fb5b46
MKG
1104
1105 }
1106};
1107
3ffc5f4f
MKG
1108sub FindDependencies {
1109 my $self = shift;
1110 my ($walker, $deps) = @_;
1111
1112 $self->SUPER::FindDependencies($walker, $deps);
1113
1114 $deps->Add( out => $self->ScripConditionObj );
1115 $deps->Add( out => $self->ScripActionObj );
1116 $deps->Add( out => $self->QueueObj ) if $self->QueueObj->Id;
1117 $deps->Add( out => $self->TemplateObj );
1118}
1119
1120sub PreInflate {
1121 my $class = shift;
1122 my ($importer, $uid, $data) = @_;
1123
1124 $class->SUPER::PreInflate( $importer, $uid, $data );
1125
1126 if ($data->{Queue} == 0) {
1127 my $obj = RT::Scrip->new( RT->SystemUser );
1128 $obj->LoadByCols( Queue => 0, Description => $data->{Description} );
1129 if ($obj->Id) {
1130 $importer->Resolve( $uid => ref($obj) => $obj->Id );
1131 return;
1132 }
1133 }
1134
1135 return 1;
1136}
1137
84fb5b46
MKG
1138RT::Base->_ImportOverlays();
1139
11401;