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