This commit was generated by cvs2svn to compensate for changes in r3921,
[freeside.git] / rt / lib / RT / Template_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 # Portions Copyright 2000 Tobias Brox <tobix@cpan.org> 
47
48 =head1 NAME
49
50   RT::Template - RT's template object
51
52 =head1 SYNOPSIS
53
54   use RT::Template;
55
56 =head1 DESCRIPTION
57
58
59 =head1 METHODS
60
61 =begin testing
62
63 ok(require RT::Template);
64
65 =end testing
66
67 =cut
68
69 use strict;
70 no warnings qw(redefine);
71
72 use Text::Template;
73 use MIME::Entity;
74 use MIME::Parser;
75 use File::Temp qw /tempdir/;
76
77
78 # {{{ sub _Accessible 
79
80 sub _Accessible {
81     my $self = shift;
82     my %Cols = (
83         id            => 'read',
84         Name          => 'read/write',
85         Description   => 'read/write',
86         Type          => 'read/write',    #Type is one of Action or Message
87         Content       => 'read/write',
88         Queue         => 'read/write',
89         Creator       => 'read/auto',
90         Created       => 'read/auto',
91         LastUpdatedBy => 'read/auto',
92         LastUpdated   => 'read/auto'
93     );
94     return $self->SUPER::_Accessible( @_, %Cols );
95 }
96
97 # }}}
98
99 # {{{ sub _Set
100
101 sub _Set {
102     my $self = shift;
103
104     # use super::value or we get acl blocked
105     if ( ( defined $self->SUPER::_Value('Queue') )
106         && ( $self->SUPER::_Value('Queue') == 0 ) )
107     {
108         unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'ModifyTemplate') ) {
109             return ( 0, $self->loc('Permission Denied') );
110         }
111     }
112     else {
113
114         unless ( $self->CurrentUserHasQueueRight('ModifyTemplate') ) {
115             return ( 0, $self->loc('Permission Denied') );
116         }
117     }
118     return ( $self->SUPER::_Set(@_) );
119
120 }
121
122 # }}}
123
124 # {{{ sub _Value 
125
126 =head2 _Value
127
128 Takes the name of a table column.
129 Returns its value as a string, if the user passes an ACL check
130
131
132 =begin testing
133
134 my $t = RT::Template->new($RT::SystemUser);
135 $t->Create(Name => "Foo", Queue => 1);
136 my $t2 = RT::Template->new($RT::Nobody);
137 $t2->Load($t->Id);
138 ok($t2->QueueObj->id, "Got the template's queue objet");
139
140 =end testing
141
142
143
144 =cut
145
146 sub _Value {
147
148     my $self  = shift;
149     my $field = shift;
150
151    
152     #If the current user doesn't have ACLs, don't let em at it.  
153     #use super::value or we get acl blocked
154     if ( ( !defined $self->__Value('Queue') )
155         || ( $self->__Value('Queue') == 0 ) )
156     {
157         unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'ShowTemplate') ) {
158             return (undef);
159         }
160     }
161     else {
162         unless ( $self->CurrentUserHasQueueRight('ShowTemplate') ) {
163             return (undef);
164         }
165     }
166     return ( $self->__Value($field) );
167
168 }
169
170 # }}}
171
172 # {{{ sub Load
173
174 =head2 Load <identifer>
175
176 Load a template, either by number or by name
177
178 =cut
179
180 sub Load {
181     my $self       = shift;
182     my $identifier = shift;
183
184     if ( !$identifier ) {
185         return (undef);
186     }
187
188     if ( $identifier !~ /\D/ ) {
189         $self->SUPER::LoadById($identifier);
190     }
191     else {
192         $self->LoadByCol( 'Name', $identifier );
193
194     }
195 }
196
197 # }}}
198
199 # {{{ sub LoadGlobalTemplate
200
201 =head2 LoadGlobalTemplate NAME
202
203 Load the global tempalte with the name NAME
204
205 =cut
206
207 sub LoadGlobalTemplate {
208     my $self = shift;
209     my $id   = shift;
210
211     return ( $self->LoadQueueTemplate( Queue => 0, Name => $id ) );
212 }
213
214 # }}}
215
216 # {{{ sub LoadQueueTemplate
217
218 =head2  LoadQueueTemplate (Queue => QUEUEID, Name => NAME)
219
220 Loads the Queue template named NAME for Queue QUEUE.
221
222 =cut
223
224 sub LoadQueueTemplate {
225     my $self = shift;
226     my %args = (
227         Queue => undef,
228         Name  => undef,
229         @_
230     );
231
232     return ( $self->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} ) );
233
234 }
235
236 # }}}
237
238 # {{{ sub Create
239
240 =head2 Create
241
242 Takes a paramhash of Content, Queue, Name and Description.
243 Name should be a unique string identifying this Template.
244 Description and Content should be the template's title and content.
245 Queue should be 0 for a global template and the queue # for a queue-specific 
246 template.
247
248 Returns the Template's id # if the create was successful. Returns undef for
249 unknown database failure.
250
251
252 =cut
253
254 sub Create {
255     my $self = shift;
256     my %args = (
257         Content     => undef,
258         Queue       => 0,
259         Description => '[no description]',
260         Type => 'Action',    #By default, template are 'Action' templates
261         Name => undef,
262         @_
263     );
264
265     if ( !$args{'Queue'}  ) {
266         unless ( $self->CurrentUser->HasRight(Right =>'ModifyTemplate', Object => $RT::System) ) {
267             return (undef);
268         }
269         $args{'Queue'} = 0;
270     }
271     else {
272         my $QueueObj = new RT::Queue( $self->CurrentUser );
273         $QueueObj->Load( $args{'Queue'} ) || return ( 0, $self->loc('Invalid queue') );
274     
275         unless ( $QueueObj->CurrentUserHasRight('ModifyTemplate') ) {
276             return (undef);
277         }
278         $args{'Queue'} = $QueueObj->Id;
279     }
280
281     my $result = $self->SUPER::Create(
282         Content => $args{'Content'},
283         Queue   =>  $args{'Queue'},
284         Description => $args{'Description'},
285         Name        => $args{'Name'}
286     );
287
288     return ($result);
289
290 }
291
292 # }}}
293
294 # {{{ sub Delete
295
296 =head2 Delete
297
298 Delete this template.
299
300 =cut
301
302 sub Delete {
303     my $self = shift;
304
305     unless ( $self->CurrentUserHasQueueRight('ModifyTemplate') ) {
306         return ( 0, $self->loc('Permission Denied') );
307     }
308
309     return ( $self->SUPER::Delete(@_) );
310 }
311
312 # }}}
313
314 # {{{ sub MIMEObj
315 sub MIMEObj {
316     my $self = shift;
317     return ( $self->{'MIMEObj'} );
318 }
319
320 # }}}
321
322 # {{{ sub Parse 
323
324 =item Parse
325
326  This routine performs Text::Template parsing on the template and then
327  imports the results into a MIME::Entity so we can really use it
328  It returns a tuple of (val, message)
329  If val is 0, the message contains an error message
330
331 =cut
332
333 sub Parse {
334     my $self = shift;
335
336     #We're passing in whatever we were passed. it's destined for _ParseContent
337     my $content = $self->_ParseContent(@_);
338
339     #Lets build our mime Entity
340
341     my $parser = MIME::Parser->new();
342
343         # On some situations TMPDIR is non-writable. sad but true.
344         $parser->output_to_core(1);
345         $parser->tmp_to_core(1);
346
347     #If someone includes a message, don't extract it
348     $parser->extract_nested_messages(1);
349
350     # Set up the prefix for files with auto-generated names:
351     $parser->output_prefix("part");
352
353     # If content length is <= 50000 bytes, store each msg as in-core scalar;
354     # Else, write to a disk file (the default action):
355     $parser->output_to_core(50000);
356
357     ### Should we forgive normally-fatal errors?
358     $parser->ignore_errors(1);
359     $self->{'MIMEObj'} = eval { $parser->parse_data($content) };
360     my $error = ( $@ || $parser->last_error );
361
362     if ($error) {
363         $RT::Logger->error("$error");
364         return ( 0, $error );
365     }
366
367     # Unfold all headers
368     $self->{'MIMEObj'}->head->unfold();
369
370     return ( 1, $self->loc("Template parsed") );
371
372 }
373
374 # }}}
375
376 # {{{ sub _ParseContent
377
378 # Perform Template substitutions on the template
379
380 sub _ParseContent {
381     my $self = shift;
382     my %args = (
383         Argument       => undef,
384         TicketObj      => undef,
385         TransactionObj => undef,
386         @_
387     );
388
389     no warnings 'redefine';
390     $T::Ticket      = $args{'TicketObj'};
391     $T::Transaction = $args{'TransactionObj'};
392     $T::Argument    = $args{'Argument'};
393     $T::Requestor   = eval { $T::Ticket->Requestors->UserMembersObj->First->Name };
394     $T::rtname      = $RT::rtname;
395     *T::loc         = sub { $T::Ticket->loc(@_) };
396
397     # We need to untaint the content of the template, since we'll be working
398     # with it
399     my $content = $self->Content();
400     $content =~ s/^(.*)$/$1/;
401     my $template = Text::Template->new(
402         TYPE   => 'STRING',
403         SOURCE => $content
404     );
405
406     my $retval = $template->fill_in( PACKAGE => 'T' );
407
408     # MIME::Parser has problems dealing with high-bit utf8 data.
409     Encode::_utf8_off($retval);
410     return ($retval);
411 }
412
413 # }}}
414
415 # {{{ sub CurrentUserHasQueueRight
416
417 =head2 CurrentUserHasQueueRight
418
419 Helper function to call the template's queue's CurrentUserHasQueueRight with the passed in args.
420
421 =cut
422
423 sub CurrentUserHasQueueRight {
424     my $self = shift;
425     return ( $self->QueueObj->CurrentUserHasRight(@_) );
426 }
427
428 # }}}
429
430 1;