import rt 3.4.4
[freeside.git] / rt / lib / RT / Scrips_Overlay.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2
3 # COPYRIGHT:
4 #  
5 # This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
6 #                                          <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27
28 # CONTRIBUTION SUBMISSION POLICY:
29
30 # (The following paragraph is not intended to limit the rights granted
31 # to you to modify and distribute this software under the terms of
32 # the GNU General Public License and is only of importance to you if
33 # you choose to contribute your changes and enhancements to the
34 # community by submitting them to Best Practical Solutions, LLC.)
35
36 # By intentionally submitting any modifications, corrections or
37 # derivatives to this work, or any other work intended for use with
38 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
39 # you are the copyright holder for those contributions and you grant
40 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
41 # royalty-free, perpetual, license to use, copy, create derivative
42 # works based on those contributions, and sublicense and distribute
43 # those contributions and any derivatives thereof.
44
45 # END BPS TAGGED BLOCK }}}
46
47 =head1 NAME
48
49   RT::Scrips - a collection of RT Scrip objects
50
51 =head1 SYNOPSIS
52
53   use RT::Scrips;
54
55 =head1 DESCRIPTION
56
57
58 =head1 METHODS
59
60
61 =begin testing
62
63 ok (require RT::Scrips);
64
65 =end testing
66
67 =cut
68
69
70 package RT::Scrips;
71
72 use strict;
73 no warnings qw(redefine);
74
75 # {{{ sub LimitToQueue 
76
77 =head2 LimitToQueue
78
79 Takes a queue id (numerical) as its only argument. Makes sure that 
80 Scopes it pulls out apply to this queue (or another that you've selected with
81 another call to this method
82
83 =cut
84
85 sub LimitToQueue  {
86    my $self = shift;
87   my $queue = shift;
88  
89   $self->Limit (ENTRYAGGREGATOR => 'OR',
90                 FIELD => 'Queue',
91                 VALUE => "$queue")
92       if defined $queue;
93   
94 }
95 # }}}
96
97 # {{{ sub LimitToGlobal
98
99 =head2 LimitToGlobal
100
101 Makes sure that 
102 Scopes it pulls out apply to all queues (or another that you've selected with
103 another call to this method or LimitToQueue
104
105 =cut
106
107
108 sub LimitToGlobal  {
109    my $self = shift;
110  
111   $self->Limit (ENTRYAGGREGATOR => 'OR',
112                 FIELD => 'Queue',
113                 VALUE => 0);
114   
115 }
116 # }}}
117
118 # {{{ sub NewItem 
119 sub NewItem  {
120   my $self = shift;
121   
122   return(new RT::Scrip($self->CurrentUser));
123 }
124 # }}}
125
126 # {{{ sub Next 
127
128 =head2 Next
129
130 Returns the next scrip that this user can see.
131
132 =cut
133   
134 sub Next {
135     my $self = shift;
136     
137     
138     my $Scrip = $self->SUPER::Next();
139     if ((defined($Scrip)) and (ref($Scrip))) {
140
141         if ($Scrip->CurrentUserHasRight('ShowScrips')) {
142             return($Scrip);
143         }
144         
145         #If the user doesn't have the right to show this scrip
146         else {  
147             return($self->Next());
148         }
149     }
150     #if there never was any scrip
151     else {
152         return(undef);
153     }   
154     
155 }
156 # }}}
157
158 =head2 Apply
159
160 Run through the relevant scrips. 
161
162 =cut
163
164 sub Apply {
165     my $self = shift;
166
167     my %args = ( TicketObj      => undef,
168                  Ticket         => undef,
169                  Transaction    => undef,
170                  TransactionObj => undef,
171                  Stage          => undef,
172                  Type           => undef,
173                  @_ );
174
175     $self->Prepare(%args);
176     $self->Commit();
177
178 }
179
180 =head2 Commit
181
182 Commit all of this object's prepared scrips
183
184 =cut
185
186 sub Commit {
187     my $self = shift;
188
189     
190     foreach my $scrip (@{$self->Prepared}) {
191
192         $scrip->Commit( TicketObj      => $self->{'TicketObj'},
193                         TransactionObj => $self->{'TransactionObj'} );
194     }
195 }
196
197
198 =head2 Prepare
199
200 Only prepare the scrips, returning an array of the scrips we're interested in
201 in order of preparation, not execution
202
203 =cut
204
205 sub Prepare { 
206     my $self = shift;
207     my %args = ( TicketObj      => undef,
208                  Ticket         => undef,
209                  Transaction    => undef,
210                  TransactionObj => undef,
211                  Stage          => undef,
212                  Type           => undef,
213                  @_ );
214
215     #We're really going to need a non-acled ticket for the scrips to work
216     $self->_SetupSourceObjects( TicketObj      => $args{'TicketObj'},
217                                 Ticket         => $args{'Ticket'},
218                                 TransactionObj => $args{'TransactionObj'},
219                                 Transaction    => $args{'Transaction'} );
220
221
222     $self->_FindScrips( Stage => $args{'Stage'}, Type => $args{'Type'} );
223
224
225     #Iterate through each script and check it's applicability.
226     while ( my $scrip = $self->Next() ) {
227
228         next
229           unless ( $scrip->IsApplicable(
230                                      TicketObj      => $self->{'TicketObj'},
231                                      TransactionObj => $self->{'TransactionObj'}
232                    ) );
233
234         #If it's applicable, prepare and commit it
235         next
236           unless ( $scrip->Prepare( TicketObj      => $self->{'TicketObj'},
237                                     TransactionObj => $self->{'TransactionObj'}
238                    ) );
239         push @{$self->{'prepared_scrips'}}, $scrip;
240
241     }
242
243     return (@{$self->Prepared});
244
245 };
246
247 =head2 Prepared
248
249 Returns an arrayref of the scrips this object has prepared
250
251
252 =cut
253
254 sub Prepared {
255     my $self = shift;
256     return ($self->{'prepared_scrips'} || []);
257 }
258
259
260 # {{{ sup _SetupSourceObjects
261
262 =head2  _SetupSourceObjects { TicketObj , Ticket, Transaction, TransactionObj }
263
264 Setup a ticket and transaction for this Scrip collection to work with as it runs through the 
265 relevant scrips.  (Also to figure out which scrips apply)
266
267 Returns: nothing
268
269 =cut
270
271
272 sub _SetupSourceObjects {
273
274     my $self = shift;
275     my %args = ( 
276             TicketObj => undef,
277             Ticket => undef,
278             Transaction => undef,
279             TransactionObj => undef,
280             @_ );
281
282     if ( ( $self->{'TicketObj'} = $args{'TicketObj'} ) ) {
283         $self->{'TicketObj'}->CurrentUser( $self->CurrentUser );
284     }
285     else {
286         $self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser );
287         $self->{'TicketObj'}->Load( $args{'Ticket'} )
288           || $RT::Logger->err("$self couldn't load ticket $args{'Ticket'}\n");
289     }
290
291     if ( ( $self->{'TransactionObj'} = $args{'TransactionObj'} ) ) {
292         $self->{'TransactionObj'}->CurrentUser( $self->CurrentUser );
293     }
294     else {
295         $self->{'TransactionObj'} = RT::Transaction->new( $self->CurrentUser );
296         $self->{'TransactionObj'}->Load( $args{'Transaction'} )
297           || $RT::Logger->err( "$self couldn't load transaction $args{'Transaction'}\n");
298     }
299
300
301 # }}}
302
303 # {{{ sub _FindScrips;
304
305 =head2 _FindScrips
306
307 Find only the apropriate scrips for whatever we're doing now
308
309 =cut
310
311 sub _FindScrips {
312     my $self = shift;
313     my %args = (
314                  Stage => undef,
315                  Type => undef,
316                  @_ );
317
318
319     $self->LimitToQueue( $self->{'TicketObj'}->QueueObj->Id )
320       ;    #Limit it to  $Ticket->QueueObj->Id
321     $self->LimitToGlobal();
322       # or to "global"
323
324     $self->Limit( FIELD => "Stage", VALUE => $args{'Stage'} );
325
326     my $ConditionsAlias = $self->NewAlias('ScripConditions');
327
328     $self->Join(
329         ALIAS1 => 'main',
330         FIELD1 => 'ScripCondition',
331         ALIAS2 => $ConditionsAlias,
332         FIELD2 => 'id'
333     );
334
335     #We only want things where the scrip applies to this sort of transaction
336     # TransactionBatch stage can define list of transaction
337     foreach( split /\s*,\s*/, ($args{'Type'} || '') ) {
338         $self->Limit(
339             ALIAS           => $ConditionsAlias,
340             FIELD           => 'ApplicableTransTypes',
341             OPERATOR        => 'LIKE',
342             VALUE           => $_,
343             ENTRYAGGREGATOR => 'OR',
344         )
345     }
346
347     # Or where the scrip applies to any transaction
348     $self->Limit(
349         ALIAS           => $ConditionsAlias,
350         FIELD           => 'ApplicableTransTypes',
351         OPERATOR        => 'LIKE',
352         VALUE           => "Any",
353         ENTRYAGGREGATOR => 'OR',
354     );
355
356     $RT::Logger->debug("Found ".$self->Count. " scrips");
357 }
358
359 # }}}
360
361 1;
362